Tôi đang cố gắng hiểu lợi ích của việc xây dựng SQL thông qua một DSL xây dựng hướng đối tượng và tham số hóa chuỗi SQL thô. Sau khi nghiên cứu/thực hiện cùng một truy vấn theo ba cách, tôi nhận thấy rằng SQL thô là dễ đọc nhất. Điều này đặt ra câu hỏi, "tại sao nhảy qua một vòng?" Tại sao không chỉ khai báo và sử dụng SQL thô?Tại sao sử dụng trình tạo SQL? Arel v. Phần tiếp theo v. T-SQL
Đây là những gì tôi đã đi lên:
Trước tiên, tôi đoán nó làm cho SQL cầm tay hơn vì nó sau đó có thể được sử dụng bởi bất kỳ DB với một adapter. Tôi đoán đây là biggie, phải không? Tuy nhiên, không phải là hầu hết T-SQL dễ hiểu đối với hầu hết các cơ sở dữ liệu?
Thứ hai, nó cung cấp một đối tượng truy vấn có thể được tái sử dụng - làm cơ sở cho các truy vấn khác, tên-phạm vi chaining vv
sự trở lại chính về đầu tư bạn nhận ra bằng cách xây dựng SQL của bạn thay vì tuyên bố là gì nó?
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
Tôi hoàn toàn đánh giá cao phạm vi được đặt tên và xem cách chuỗi chúng có thể mang lại lợi ích. Tôi không lo lắng về việc truy cập các hồ sơ liên quan thông qua một mô hình. Tôi hoàn toàn nói về việc xây dựng một truy vấn phức tạp.
_ "Thứ hai, nó cung cấp đối tượng truy vấn có thể được sử dụng lại - làm cơ sở cho các truy vấn khác, chuỗi phạm vi được đặt tên, v.v." _ Đó là một lý do tôi sử dụng phần tiếp theo, cũng như thực tế được gán cho các mô hình cho phép tôi viết mã Ruby mô tả ngắn, đôi khi có thể tạo ra SQL phức tạp. Tuy nhiên, cách sử dụng tốt nhất mà tôi gặp phải là trong một trang tìm kiếm phức tạp, nơi một loạt các thành phần giao diện người dùng cho phép tôi điều chỉnh truy vấn từ từ và có điều kiện khi tôi xử lý các tùy chọn tìm kiếm. – Phrogz
Phát hiện câu hỏi. Tôi thường thấy mình dành 10% thời gian để viết truy vấn thực tế và 90% thời gian dịch nó sang cú pháp ORM, hầu hết các vấn đề với việc nhóm và biểu thức tổng hợp, kết hợp với các bảng có nhiều bí danh. –
@Phrogz: Bạn nên làm điều đó một câu trả lời, như tinh chỉnh các truy vấn bằng cách sử dụng Ruby thực sự là một trong những lợi thế lớn nhất của ORMs, IMO. Dễ dàng hơn nhiều khi bạn có nó trong phương pháp xích hơn khắc nó bằng dây. –