8 Stimmen

Warum SQL-Builder verwenden? Arel vs. Sequel vs. T-SQL

Ich versuche zu verstehen, die Vorteile der Erstellung von SQL über eine objektorientierte Builder-DSL vs. Parametrisierung eine rohe SQL-Zeichenfolge. Nachdem ich dieselbe Abfrage auf drei verschiedene Arten untersucht/implementiert habe, stelle ich fest, dass die Roh-SQL bei weitem am einfachsten zu lesen ist. Das wirft die Frage auf: "Warum sich die Mühe machen?" Warum nicht einfach rohes SQL deklarieren und verwenden?

Das habe ich mir ausgedacht:

Erstens macht es das SQL portabler, da es dann von jeder DB mit einem Adapter verwendet werden kann. Ich denke, das ist das Wichtigste, oder? Aber ist nicht das meiste T-SQL für die meisten Datenbanken verständlich?

Zweitens bietet es ein Abfrageobjekt, das wiederverwendet werden kann - als Grundlage für andere Abfragen, Verkettung von benannten Bereichen usw.

Was ist der größte Nutzen, den Sie erzielen, wenn Sie Ihr SQL aufbauen, anstatt es zu deklarieren?

def instances_of_sql(ttype_id) #raw sql
  ttype_id = get(ttype_id).try(:id)
  ti   = get('tmdm:type-instance')
  inst = get('tmdm:instance')
  type = get('tmdm:type')

  self.class.send :sanitize_sql, [%{
    SELECT t.*
    FROM associations a
    JOIN roles type    ON type.association_id = a.id AND type.ttype_id = ?
    JOIN roles inst    ON inst.association_id = a.id AND inst.ttype_id = ?
    JOIN topics t      ON t.id = inst.topic_id
    WHERE a.topic_map_id IN (?)
    AND a.ttype_id    = ?
    AND type.topic_id = ?
  }, type.id, inst.id, self.ids, ti.id, ttype_id]
end

def instances_of_sql(ttype_id) #sequel
  ttype_id = get(ttype_id).try(:id)
  ti = get('tmdm:type-instance')
  ir = get('tmdm:instance')
  tr = get('tmdm:type')

  DB.from(:associations.as(:a)).
    join(:roles.as(:tr), :tr__association_id => :a__id, :tr__ttype_id => tr[:id]).
    join(:roles.as(:ir), :ir__association_id => :a__id, :ir__ttype_id => ir[:id]).
    join(:topics.as(:t), :t__id => :ir__topic_id).
    where(:a__topic_map_id => self.ids).
    where(:a__ttype_id => ti[:id]).
    where(:tr__topic_id => ttype_id).
    select(:t.*).sql
end

def instances_of_sql(ttype_id) #arel
  ttype_id = get(ttype_id).try(:id)
  ti   = get('tmdm:type-instance')
  inst = get('tmdm:instance')
  type = get('tmdm:type')

  #tables
  t    = Topic.arel_table
  a    = Association.arel_table
  tr   = Role.arel_table
  ir   = tr.alias

  a.
    join(tr).on(tr[:association_id].eq(a[:id]),tr[:ttype_id].eq(type[:id])).
    join(ir).on(ir[:association_id].eq(a[:id]),ir[:ttype_id].eq(inst[:id])).
    join(t).on(t[:id].eq(ir[:topic_id])).
    where(a[:topic_map_id].in(self.ids)).
    where(a[:ttype_id].eq(ti[:id])).
    where(tr[:topic_id].eq(ttype_id)).
    project('topics.*').to_sql
end

Ich schätze benannte Bereiche sehr und verstehe, wie eine Verkettung von ihnen von Vorteil sein kann. Ich bin nicht besorgt über den Zugriff auf Bezugsdatensätze über ein Modell. Ich spreche nur über den Aufbau einer komplexen Abfrage.

8voto

ian Punkte 11473

Der Link, den @Kyle Heironimus zu Nick Kallens Gedanken über Arel angegeben hat, enthielt diese Zeile:

Sie werden feststellen, dass die Verwendung des abgeleiteten Tabelle in der Unterauswahl. Dies ist schrecklich, meiner Meinung nach. Nur fortgeschrittene SQL-Programmierer wissen, wie man so etwas schreibt (Ich habe diese Frage oft in Vorstellungsgesprächen gestellt Vorstellungsgesprächen gestellt, aber ich habe noch nie gesehen, dass es jemand richtig gemacht hat). Und es sollte nicht schwer sein!

Nun, Kallen führt dies auf die mangelnde Geschlossenheit der Komposition in SQL zurück. Das mag in einigen Fällen zutreffen, aber meine Erfahrung ist viel prosaischer - die meisten Entwickler sind schrecklich in SQL. Sie kennen nur die grundlegendsten Dinge, und diese grundlegenden Dinge werden missbraucht, wenn sie versuchen, in einer mengenbasierten Sprache nach prozeduralen Lösungen zu suchen. In einem Unternehmen, in dem ich tätig war, musste ich die Vorteile einer Datenbank in 3NF mit folgenden Argumenten belegen tous die anderen Entwickler, sie haben es einfach nicht verstanden. Talentierte Leute (die meisten von ihnen:), aber keine Ahnung von SQL oder Datenbanken.

Geben Sie es in C# oder Ruby oder Python <Name der Sprache> ein, und die Entwickler sind wieder zufrieden. Sie können mit prozeduralem/OO-Denken weitermachen und Code produzieren, der für sie gut aussieht.

Ich weiß, dass mir das keine Stimmen einbringen wird, wahrscheinlich eher das Gegenteil, aber es ist meine Meinung. Arel sieht übrigens interessant aus.


Als Nachtrag zu meinen obigen Ausführungen kann ich nach mehr als sechs Monaten, in denen ich die Sequel-Bibliothek viel benutzt habe, sagen, dass sie in der Tat eine wunderbare Sache ist, und jetzt habe ich das Gefühl, dass ich sie benutzen würde voraus der Verwendung von einfachem SQL. Es ist nicht nur unglaublich leistungsfähig und ermöglicht es mir, einfache und fortgeschrittene Dinge zu tun, ohne zu viel Kopfkratzen (es wird immer welche geben), es kann das verwendete SQL ausgeben, und es erlaubt mir auch, in SQL abzusteigen, wenn ich das Gefühl habe, dass ich es brauche.

Dies entkräftet in keiner Weise meine Bemerkungen über das SQL-Verständnis der meisten Entwickler (mir wurde kürzlich von einem Entwickler, der Vorträge für andere hält, gesagt, dass die Normalisierung ein Relikt aus einer Zeit sei, in der Speicherplatz teuer war... oh je!), nur dass die Entwicklung der Sequel-Bibliothek offensichtlich von denjenigen durchgeführt wurde, die wirklich etwas von Datenbanken verstehen. Wenn man sich mit SQL und dem Design von Datenbanken usw. auskennt, erhält man schneller mehr Leistung. Das kann ich von den anderen ORMs, die ich benutzt habe, nicht behaupten, aber vielleicht denken andere anders darüber.

4voto

Kyle Heironimus Punkte 7363

Sie haben die Gründe dafür schon ziemlich gut auf den Punkt gebracht.

Hier sind Gedanken des Schöpfers von Arel.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X