在我学习Ruby的过程中,我一直在阅读Mr. Neighborly's Humble Little Ruby Book。
大多数示例都很容易理解,为我提供了很好的Ruby介绍,但是我无法轻松地运行与DB相关的示例。
我正在尝试运行此代码:(稍微修改了本书中给出的示例)
#!/usr/bin/ruby
require 'rubygems'
require 'dbi'
DBI.connect('DBI:SQLite3:testdb', 'ruby', 'ruby') do | dbh |
dbh.do('CREATE TABLE slugs(name varchar(20), age int);') rescue puts "TABLE slugs already exists."
sql = "INSERT INTO slugs (name, age) VALUES (?, ?)"
dbh.prepare(sql) do |st|
1.upto(20) do |i|
st.execute("slug #{i}", "#{i}")
end
end
end
运行时,它会在数据库中插入一行,然后它会出现以下错误:
/var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:41:in `bind_param': library routine called out of sequence (SQLite3::MisuseException) from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:41:in `bind_params' from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `each' from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `bind_params' from /var/lib/gems/1.8/gems/dbd-sqlite3-1.2.5/lib/dbd/sqlite3/statement.rb:71:in `bind_params' from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:115:in `execute' from /media/dev/ruby-prax/moi.rb:12 from /media/dev/ruby-prax/moi.rb:11:in `upto' from /media/dev/ruby-prax/moi.rb:11 from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/database.rb:61:in `prepare' from /media/dev/ruby-prax/moi.rb:10 from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/driver.rb:41:in `connect' from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi.rb:148:in `connect' from /media/dev/ruby-prax/moi.rb:5 TABLE slugs already exists.
目前我在Ubuntu 10.04上。 版本信息:
tlee@tim-ubuntu:/media/dev/ruby-prax$ ruby -v ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux] tlee@tim-ubuntu:/media/dev/ruby-prax$ gem list *** LOCAL GEMS *** abstract (1.0.0) daemons (1.1.0) dbd-mysql (0.4.4) dbd-odbc (0.2.5) dbd-sqlite3 (1.2.5) dbi (0.4.5) deprecated (3.0.0, 2.0.1) erubis (2.6.6) eventmachine (0.12.10) extlib (0.9.15) json_pure (1.4.6) mysql (2.8.1) rack (1.2.1) sqlite3-ruby (1.3.2) thin (1.2.7) thor (0.14.1) tlee@tim-ubuntu:/media/dev/ruby-prax$ sqlite3 --version 3.6.22 tlee@tim-ubuntu:/media/dev/ruby-prax$
我做错了什么?
答案 0 :(得分:3)
我遇到了同样的问题。当您多次使用准备好的INSERT语句时,有关于DBD失败的SQLite驱动程序的issue on github。就个人而言,由于Ruby / DBI显然不再被维护,我已经在回答RDBI的答案中采取了建议。迁移到RDBI需要非常少的代码更改。
答案 1 :(得分:1)
您的表定义是:
slugs(name varchar(20), age int);
但你想插入:
st.execute("slug #{i}", "#{i}")
请注意"#{i}"
不是整数,而是字符串。将其更改为i
,如下例所示:
st.execute("slug #{i}", i)
然后看看会发生什么。
答案 2 :(得分:0)
我不知何故认为Ruby上的几个sqlite3库缺少语句类的重置和清除方法。
当重复执行相同的SQL语句时,会准备一次语句并使用一组新值执行。但是在执行语句之后并且在重新绑定之前,它需要被重置(并且经常被清除)。关键是重置已使用的语句比编译和优化"更快。同样的SQL一遍又一遍。大多数人可能都知道这一切......但这里是相关部分的SQLite文档的链接:
https://www.sqlite.org/c3ref/stmt.html
我没有在SQLite3 :: Statement类中看到重置和清除方法,所以这些可能会以某种方式错过此实现,或者在重用时有一些其他机制可以自动重置/清除,但是这种机制是某种方式没有触发。但是,文档中甚至没有提到它......至少我找不到它。
我认为SQLite3 :: Statement类中缺少clear_bindings和reset方法。