Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Xây dựng truy vấn động trong đường ray

Bạn có thể tạo một truy vấn SQL dựa trên hàm băm của mình. Cách tiếp cận chung nhất là SQL thô, có thể được thực thi bởi ActiveRecord .

Đây là một số mã khái niệm sẽ cung cấp cho bạn ý tưởng phù hợp:

query_select = "select * from "
query_where = ""
tables = [] # for selecting from all tables
hash.each do |table, values|
  table_name = table.constantize.table_name
  tables << table_name
  values.each do |q|
    query_where += " AND " unless query_string.empty?
    query_where += "'#{ActiveRecord::Base.connection.quote(table_name)}'."
    query_where += "'#{ActiveRecord::Base.connection.quote(q[fieldName)}'"
    if q[:operator] == "starts with" # this should be done with an appropriate method
      query_where += " LIKE '#{ActiveRecord::Base.connection.quote(q[val)}%'"
    end
  end
end
query_tables = tables.join(", ")
raw_query = query_select + query_tables + " where " + query_where 
result = ActiveRecord::Base.connection.execute(raw_query)
result.to_h # not required, but raw results are probably easier to handle as a hash

Điều này có tác dụng gì:

  • query_select chỉ định thông tin bạn muốn trong kết quả
  • query_where xây dựng tất cả các điều kiện tìm kiếm và thoát đầu vào để ngăn chặn việc đưa vào SQL
  • query_tables là danh sách tất cả các bảng bạn cần tìm kiếm
  • table_name = table.constantize.table_name sẽ cung cấp cho bạn tên_bảng SQL như được sử dụng bởi mô hình
  • raw_query là truy vấn sql kết hợp thực tế từ các phần trên
  • ActiveRecord::Base.connection.execute(raw_query) thực thi sql trên cơ sở dữ liệu

Đảm bảo đặt bất kỳ đầu vào nào do người dùng gửi trong dấu ngoặc kép và thoát nó đúng cách để ngăn việc đưa vào SQL.

Đối với ví dụ của bạn, truy vấn đã tạo sẽ giống như sau:

select * from companies, categories where 'companies'.'name' LIKE 'a%' AND 'companies'.'hq_city' = 'karachi' AND 'categories'.'name' NOT LIKE '%ECommerce%'

Cách tiếp cận này có thể cần logic bổ sung để kết hợp các bảng có liên quan. Trong trường hợp của bạn, nếu companycategory có một liên kết, bạn phải thêm một cái gì đó như thế này vào query_where

"AND 'company'.'category_id' = 'categories'.'id'"

Cách tiếp cận dễ dàng: Bạn có thể tạo Hash cho tất cả các cặp mô hình / bảng có thể được truy vấn và lưu trữ điều kiện nối thích hợp ở đó. Hash này không nên quá phức tạp ngay cả đối với một dự án quy mô vừa.

Cách tiếp cận khó: Điều này có thể được thực hiện tự động, nếu bạn có has_many , has_onebelongs_to được xác định đúng trong các mô hình của bạn. Bạn có thể nhận các liên kết của một mô hình bằng cách sử dụng Reflect_on_all_associations . Triển khai Breath-First-Search hoặc Depth-First Search thuật toán và bắt đầu với bất kỳ mô hình nào và tìm kiếm các liên kết phù hợp với các mô hình khác từ đầu vào json của bạn. Bắt đầu chạy BFS / DFS mới cho đến khi không còn mô hình nào chưa được duyệt từ đầu vào json bên trái. Từ thông tin tìm được, bạn có thể lấy tất cả các điều kiện kết hợp và sau đó thêm chúng dưới dạng biểu thức trong where mệnh đề của cách tiếp cận sql thô như đã giải thích ở trên. Thậm chí phức tạp hơn, nhưng cũng có thể làm được là đọc schema cơ sở dữ liệu và sử dụng cách tiếp cận tương tự như được định nghĩa ở đây bằng cách tìm kiếm foreign keys .

Sử dụng liên kết: Nếu tất cả chúng được liên kết với has_many / has_one , bạn có thể xử lý các phép nối bằng ActiveRecord bằng cách sử dụng joins phương pháp với inject trên mô hình "quan trọng nhất" như thế này:

base_model = "Company".constantize
assocations = [:categories]  # and so on
result = assocations.inject(base_model) { |model, assoc| model.joins(assoc) }.where(query_where)

Điều này có tác dụng gì:

  • nó chuyển base_model làm đầu vào bắt đầu tới Enumerable.inject , sẽ liên tục gọi input.send (:joins,:assoc) (ví dụ của tôi, điều này sẽ thực hiện Company.send(:joins, :categories) tương đương với `Company.categories
  • trên phép nối kết hợp, nó thực thi các điều kiện where (được xây dựng như mô tả ở trên)

Tuyên bố từ chối trách nhiệm Cú pháp chính xác bạn cần có thể thay đổi tùy theo cách triển khai SQL mà bạn sử dụng.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lợi ích lớn nhất của việc sử dụng INDEXES trong mysql là gì?

  2. Làm thế nào để điền vào một bảng với một phạm vi ngày?

  3. MySQL khôi phục trên giao dịch với kết nối bị mất / ngắt kết nối

  4. PDO-MySQL:Giá trị Boolean được chuyển đổi thành 1 hoặc chuỗi trống trên liên kết câu lệnh đã chuẩn bị

  5. bảng được chỉ định hai lần vừa là mục tiêu cho INSERT vừa là nguồn dữ liệu riêng biệt