1

我有一个示例字符串“Canon PowerShot 12.1-Megapixel”,当我运行以下代码时,它似乎失败了:

db.execute "CREATE TABLE IF NOT EXISTS Products( id INTEGER PRIMARY KEY, stockID INTEGER, Name TEXT )" 

id = 12345
name = "Canon PowerShot 12.1-Megapixel"       

db.execute( "INSERT INTO Products ( stockID, Name ) VALUES ( #{id}, #{name} )" )

错误代码是:

C:/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/lib/sqlite3/d
atabase.rb:91:in `initialize': near "PowerShot": syntax error
(SQLite3::SQLExcep tion)
        from C:/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/
lib/sqlite3/database.rb:91:in `new'
        from C:/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/
lib/sqlite3/database.rb:91:in `prepare'
        from C:/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/
lib/sqlite3/database.rb:134:in `execute'
        from E:/Documents/Cowboom/scraping/DBDOTDList.rb:48:in `<main>'

知道为什么这会在“PowerShot”之后死掉吗?

4

1 回答 1

13

您正在创建的字符串周围没有引号。所以字符串实际上是这样出来的:

"INSERT INTO Products ( stockID, Name ) VALUES ( 12345, Canon PowerShot 12.1-Megapixel )"

如您所见,这是无效的 SQL;它将尝试解释Canon PowerSho 12.1-Megapixel为 SQL 语句的一部分,而不是字符串。

您可以尝试通过在变量插值周围加上引号来解决此问题:

db.execute( "INSERT INTO Products ( stockID, Name ) VALUES ( #{id}, '#{name}' )" )

但是,总的来说,这是一个坏主意。如果字符串最终包含 a ',那么这将在 SQL 语句中结束该字符串,从而导致错误(或者更糟糕的是,如果攻击者这样做,则会出现SQL 注入漏洞;请参阅此漫画以获取有趣的示例)。您通常应该避免尝试通过插入或附加字符串来构建 SQL 查询;您可能认为您可以过滤掉或引用错误的字符,但这实际上很难做到。

相反,您应该对传递给 SQL 语句的任何变量数据使用绑定参数:

db.execute( "INSERT INTO Products ( stockID, Name ) VALUES ( ?, ? )", [id, name])

有关更多信息和示例,请参阅sqlite3-ruby 文档

于 2012-11-19T21:05:24.840 回答