我正在读重建铁路的书。在小orm一章中,它使用sqlite3 gem与sqlite数据库通信。
my_table数据库结构
create table my_table (
id INTEGER PRIMARY KEY,
posted INTEGER,
title VARCHAR(30),
body VARCHAR(32000));
在.rb文件中插入my_表的代码是:
DB.execute <<-SQL
INSERT INTO #{table} (#{keys.join ","})
VALUES (#{vals.join ","});
SQL
# vals=>["1", "It happend!", "It did!"]
但它所转为的sql语句将是:
"INSERT INTO my_table (posted,title,body)\n VALUES (1,It happend!,It did!);\n"
由于双引号“it happend!”“是的!”
我检查了发现array join的文档,它返回一个通过将数组的每个元素转换为字符串而创建的字符串。因此,数组中的双引号元素将被转换为字符串并丢失双引号。并导致SQL语法错误。
如何解决这个问题?
任何帮助都将不胜感激!
谢谢!
最佳答案
像这样的事情,你不应该自己做。不幸的是,mysql2
gem(我相信您正在使用的)不支持prepared语句,这是您应该这样做的;但是您可以使用其他几个gem来添加功能。
一个是mysql-cs-bind
gem,非常简单,只需将其添加到mysql2
:
client.xquery(<<-SQL, vals)
INSERT INTO #{table} (#{keys.join ","})
VALUES (#{keys.map { "?" }.join(",")});
SQL
另一种方法是使用更通用的gem,比如
sequel
,它在各种数据库中提供了很多功能,而不仅仅是mysql。你不应该自己做的原因是
这是一个解决了的问题
很容易犯错误
Bobby Tables可能会访问您的网站。
如果你必须自己做:
db.execute <<-SQL
INSERT INTO #{table} (#{keys.join ","})
VALUES (#{
vals.map { |val|
case val
when String
"'#{mysql.escape(val)}'"
when Date, Time, DateTime
"'#{val}'"
else
val
end
}.join(', ')
});
SQL
(不确定mysql想要什么格式的日期/时间值,所以可能需要调整)
编辑:幸运的是,sqlite3确实提供了准备好的语句和占位符。
DB.execute <<-SQL, *vals
INSERT INTO #{table} (#{keys.join ","})
VALUES (#{keys.map { "?" }.join(",")});
SQL
编辑:对
map
感到愚蠢。谢谢,乔丹。