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.