我正在读重建铁路的书。在小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语法错误。
如何解决这个问题?
任何帮助都将不胜感激!
谢谢!

最佳答案

像这样的事情,你不应该自己做。不幸的是,mysql2gem(我相信您正在使用的)不支持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感到愚蠢。谢谢,乔丹。

10-05 20:31
查看更多