我正在尝试通过使用单个质量插入而不是多次调用ActiveRecord的create
方法来导入数据来优化我的rake任务的性能。
这是我写的代码:
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订单(公司,编号,行,created_at,评论)VALUES (' 100',' 023074',' 001',' 2016-07-05 11:17:38','转型K7'), (' 100',' 023943',' 001',' 2016-07-05 11:17:38',' BANDE PE D' AMARRAGE')
这将生成
PG :: SyntaxError:ERROR:语法错误在或附近" AMARRAGE"
我该如何处理?
答案 0 :(得分:1)
问题是您的字符串引号正在关闭SQL查询中的字符串值。试试escaping them:
'#{ord.comment.gsub("'"){ "\\'" }'
这样,SQL查询将包含有效的字符串。
此外,你不应该做你想做的事情。如果comment
属性包含sql代码,则可能会注入,并对数据库执行令人讨厌的操作。请阅读this。安全!
答案 1 :(得分:0)
请尝试以下操作。
Order.sanitize(ord.comment)
答案 2 :(得分: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)
答案 3 :(得分: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)