我正在阅读 Rebuilding Rails 一书。在小 ORM 章节中,它使用 sqlite3 gem 与 sqlite 数据库进行通信。 my_table 数据库结构
create table my_table (
id INTEGER PRIMARY KEY,
posted INTEGER,
title VARCHAR(30),
body VARCHAR(32000));
插入到 .rb 文件中的 my_table 的代码是:
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!" 和"It did!"双引号,它会引发语法错误。 em>
我检查文档发现 Array#join 返回一个字符串,该字符串是通过将数组的每个元素转换为字符串而创建的。因此数组中的双引号元素将被转换为字符串并丢失双引号。并导致该 sql 语法错误。
如何解决?
任何帮助将不胜感激! 谢谢!
最佳答案
这样的事情,你不应该自己做。不幸的是,mysql2
gem(我相信您正在使用)不支持准备好的语句,而这正是您应该这样做的方式;但是您可以使用其他几个 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
很愚蠢。谢谢,乔丹。
关于ruby-on-rails - 如何在保持双引号的同时连接数组中的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31779243/