2016-08-26 88 views
1

ActiveRecord與編寫原始查詢有什麼區別? 在哪種情況下應該採用在rails應用程序中編寫原始查詢。ActiveRecord vs SQL原始查詢?

+0

ActiveRecord的只是一個ORM。因此,更好的問題將是爲什麼使用ORM代替原始SQL:[google](https://www.google.ca/?client=safari#q=orm+vs+sql&gfe_rd=cr) – AbM

+1

您的具體用途是什麼案件?如果您提供更多詳細信息,我可以優化我的答案? –

回答

0

ActiveRecord將在大多數時間爲您提供服務,但有幾種情況下您需要編寫原始sql。值得注意的是,ActiveRecord查詢也可以用類似sql的方式編寫。例如,你可以寫:

User.where(name: "Person A") 

或者你可以將其與一個稍微類似SQL的語法寫:

User.where("name = ?", "Person A") 
User.where("name LIKE ?", "%Person A%") 

其中之一,你可能需要編寫原始SQL的原因是,當你正嘗試訪問無法通過ActiveRecord方法訪問的內容,例如has_and_belongs_to_many關聯中的連接表。

2

關鍵的區別在於ActiveRecord通過使用更高級別的抽象讓您可以更高效地編寫代碼。

它還通過抽象出DBMS之間的一些差異使得代碼更加便攜:es。

如果您不注意ActiveRecord生成的查詢,此抽象代價有可能會導致性能問題。

在哪種情況下應該採用在rails應用程序中編寫原始查詢?

當需要完成手頭的工作。例如,這可以是使用Postgres的擴展ILIKE

# case insensitive search: 
@user = User.where('users.name ILIKE ?', params[:name]) 

或者當你需要執行一個複雜的加入或其他性能關鍵的操作。就像這個例子一樣,它會爲每個父代獲取多個關聯記錄。這聽起來很簡單,但在ActiveRecord中做起來非常困難。

class Observation < ActiveRecord::Base 
    belongs_to :station 

    # ... 

    def self.pluck_from_each_station(limit = 1) 
    ActiveRecord::Base.connection.execute(%Q{ 
     SELECT o.id 
     FROM stations s 
     JOIN LATERAL (
     SELECT id, created_at 
     FROM observations 
     WHERE station_id = s.id -- lateral reference 
     ORDER BY created_at DESC 
     LIMIT #{limit} 
    ) o ON TRUE 
     ORDER BY s.id, o.created_at DESC; 
    }).field_values('id') 
    end 
end 

最後一點,如果你不知道如何執行與ActiveRecord的操作往往是更好地寫出了位的SQL與測試支持它,回去以後重構。

@users = User.where("occupation NOT IN(?)", params[:blacklist])) # @todo fix 

然後,您可以重構這:

@users.where.not(occupation: params[:blacklist])