将Ruby String插入Sqlite

rlh*_*lhh 1 ruby sqlite string insert

我有一个示例字符串"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} )" )
Run Code Online (Sandbox Code Playgroud)

错误代码是:

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>'
Run Code Online (Sandbox Code Playgroud)

知道为什么在"PowerShot"之后死了吗?

Bri*_*ell 13

您正在创建的字符串周围没有引号.所以字符串实际上是:

"INSERT INTO Products ( stockID, Name ) VALUES ( 12345, Canon PowerShot 12.1-Megapixel )"
Run Code Online (Sandbox Code Playgroud)

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

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

db.execute( "INSERT INTO Products ( stockID, Name ) VALUES ( #{id}, '#{name}' )" )
Run Code Online (Sandbox Code Playgroud)

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

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

db.execute( "INSERT INTO Products ( stockID, Name ) VALUES ( ?, ? )", [id, name])
Run Code Online (Sandbox Code Playgroud)

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