2016-07-05 21 views
1

我想通過使用單個質量塊插入而不是多次調用ActiveRecord的create方法來導入數據來優化我的耙子任務的性能。Rails 4,單個質量塊插入

這裏是我寫的代碼:

inserts = [] 
orders.each do |ord| 
    inserts.push "('#{ord.company}', '#{ord.number}', '#{ord.line}', '#{Time.now.to_s(:db)}', '#{ord.comment}')" 
end 
sql = "INSERT INTO orders (company, number, line, created_at, comment) VALUES #{inserts.join(", ")}" 
ActiveRecord::Base.connection.execute(sql) 

的問題是,comment字符串可以包含'字符,因此生成的SQL查詢字符串看起來像:

INSERT INTO orders (company, number, line, created_at, comment) VALUES ('100', '023074', '001', '2016-07-05 11:17:38', 'TRANSFORMATION K7'), ('100', '023943', '001', '2016-07-05 11:17:38', 'BANDE PE D'AMARRAGE')

這將生成一個

PG::SyntaxError: ERROR: syntax error at or near "AMARRAGE"

我該如何處理t他?

回答

0

我最終使用ActiveRecord::Base.connection.quote方法:

inserts = [] 
orders.each do |ord| 
    company = ActiveRecord::Base.connection.quote(ord.company) 
    number = ActiveRecord::Base.connection.quote(ord.number) 
    line = ActiveRecord::Base.connection.quote(ord.line) 
    comment = ActiveRecord::Base.connection.quote(ord.comment) 
    inserts.push "(#{company}, #{number}, #{line}, '#{Time.now.to_s(:db)}', #{comment})" 
end 
sql = "INSERT INTO orders (company, number, line, created_at, comment) VALUES #{inserts.join(", ")}" 
ActiveRecord::Base.connection.execute(sql) 
1

問題是您的字符串引號正在關閉SQL查詢中的字符串值。嘗試escaping them

'#{ord.comment.gsub("'"){ "\\'" }' 

這樣,SQL查詢將包含有效的字符串。

此外,你不應該做你想做的事情。如果comment屬性包含sql代碼,可能會被注入,併爲您的數據庫做一些討厭的東西。請閱讀this。注意安全!

0

請嘗試以下操作。

Order.sanitize(ord.comment) 
0

PostgreSQL的轉義字符爲single quote。所以如果你想用connection.execute方法批量插入數據庫,那麼用two single quotes替換single quote

這裏是代碼示例。

inserts = [] 
orders.each do |ord| 
    inserts.push "('#{ord.company}', '#{ord.number}', '#{ord.line}', '#{Time.now.to_s(:db)}', '" + ord.comment.gsub("'","''") + "')" 
end 
sql = "INSERT INTO orders (company, number, line, created_at, comment) VALUES #{inserts.join(", ")}" 
ActiveRecord::Base.connection.execute(sql)