2016-07-05 2 views
1

Я пытаюсь оптимизировать производительность своей рейк-задачи, используя единую массовую вставку, вместо нескольких вызовов метода ActiveActiveRecord для импорта данных.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')

Это будет генерировать a

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, замените single quote на two single quotes

Вот пример кода.

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) 
Смежные вопросы