为什么我的简单 Ruby SQLite3 示例失败了?

发布于 2024-10-03 17:40:19 字数 2350 浏览 5 评论 0原文

在我尝试学习 Ruby 的过程中,我一直在阅读 Mr.邻居的简陋红宝石小书

大多数示例都很容易理解,为我很好地介绍了 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$ 

我做错了什么?

In my attempt to learn Ruby, I've been reading Mr. Neighborly's Humble Little Ruby Book.

Most examples have been very easy to follow giving me a good introduction to Ruby, however I can't run DB related examples easily.

I'm trying to run this code: (slightly modified from the example given in the book)

#!/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

When run, it inserts one row in the database, then it gives me the following error:

/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.

I am on Ubuntu 10.04 at the moment.
Version info:

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$ 

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌若浮生 2024-10-10 17:40:19

我遇到了同样的问题。 github 上有一个关于 DBD 的 SQLite 驱动程序失败的问题,当您多次使用准备好的 INSERT 语句。就我个人而言,我采纳了答案中的建议,即转向 RDBI,因为 Ruby/DBI 显然不是维护时间更长。迁移到 RDBI 只需要很少的代码更改。

I experienced the same problem. There is an issue on github about the SQLite driver for DBD failing when you use a prepared INSERT statement more than once. Personally, I've taken the recommendation in the answer there of moving to RDBI, since Ruby/DBI is apparently no longer being maintained. Moving to RDBI required very minimal code changes.

往日 2024-10-10 17:40:19

您的表定义是:

slugs(name varchar(20), age int);

但您尝试插入:

st.execute("slug #{i}", "#{i}")

请注意,“#{i}”不是整数,而是字符串。将其更改为 i,如本例所示:

st.execute("slug #{i}", i) 

然后看看会发生什么。

Your table definition is:

slugs(name varchar(20), age int);

but you are trying to insert:

st.execute("slug #{i}", "#{i}")

Note that "#{i}" is not an integer, it's a string. Change it to i, as in this example:

st.execute("slug #{i}", i) 

Then see what happens.

叹沉浮 2024-10-10 17:40:19

我不知何故认为 Ruby 上的几个 sqlite3 库缺少语句类的重置和清除方法。

当重复执行相同的 SQL 语句时,语句会准备一次并使用一组新的值执行。但在语句执行之后、重新绑定之前,需要对其进行重置(并且经常会被清除)。关键是,重置已使用的语句比一遍又一遍地“编译和优化”相同的 SQL 更快。大多数人可能都知道这一切...但这里是相关部分的 SQLite 文档的链接:

https://www.sqlite.org/c3ref/stmt.html

我在 SQLite3::Statement 类中没有看到重置和清除方法,因此这些实现可能会以某种方式丢失,或者还有其他一些方法重用时自动重置/清除的机制,但该机制以某种方式未触发。然而,文档中甚至没有提到它......至少我找不到它。

我认为 SQLite3::Statement 类中缺少 Clear_Bindings 和 Reset 方法。

https://github.com/sparklemotion/sqlite3-ruby/issues/158

I somehow think that several of sqlite3 libraries on Ruby are missing reset and clear methods for the statement class.

When same SQL statement is executed repeatedly, a statement is prepared once and executed with a fresh set of values. But after the statement is executed and before it is re-bound, it needs to be reset (and often cleared). The point is that it is faster to reset a used statement than "compiling and optimizing" the same SQL over and over again. Most of you probably know all this... but here's the link to the SQLite documentation of the relevant part:

https://www.sqlite.org/c3ref/stmt.html

I don't see reset and clear methods in SQLite3::Statement class, so these might be somehow missed from this implementation, or there is some other mechanism to reset/clear automatically when reused, but that mechanism is somehow not triggered. However, it is not even mentioned in the documentation... at least I couldn't find it.

I think clear_bindings and reset methods are missing from SQLite3::Statement class.

https://github.com/sparklemotion/sqlite3-ruby/issues/158

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文