【问题标题】:Why is my simple Ruby SQLite3 example failing?为什么我的简单 Ruby SQLite3 示例失败了?
【发布时间】:2011-05-14 06:32:44
【问题描述】:

在尝试学习 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': 库例程调用乱序(SQLite3::MisuseException) 来自 /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:41:in `bind_params' 来自 /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `each' 来自 /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `bind_params' 来自 /var/lib/gems/1.8/gems/dbd-sqlite3-1.2.5/lib/dbd/sqlite3/statement.rb:71:in `bind_params' 来自 /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:115:in `execute' 来自/media/dev/ruby-prax/moi.rb:12 来自 /media/dev/ruby-prax/moi.rb:11:in `upto' 来自/media/dev/ruby-prax/moi.rb:11 来自 /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/database.rb:61:in `prepare' 来自 /media/dev/ruby-prax/moi.rb:10 来自 /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/driver.rb:41:in `connect' 来自 /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi.rb:148:in `connect' 来自 /media/dev/ruby-prax/moi.rb:5 TABLE slug 已经存在。

我目前使用的是 Ubuntu 10.04。 版本信息:

tlee@tim-ubuntu:/media/dev/ruby-prax$ ruby​​ -v ruby 1.8.7 (2010-01-10 补丁级别 249) [x86_64-linux] tlee@tim-ubuntu:/media/dev/ruby-prax$ 宝石列表 *** 当地宝石 *** 摘要 (1.0.0) 守护进程 (1.1.0) dbd-mysql (0.4.4) dbd-odbc (0.2.5) dbd-sqlite3 (1.2.5) 分贝 (0.4.5) 已弃用(3.0.0、2.0.1) 厄鲁比斯 (2.6.6) 事件机(0.12.10) 扩展库 (0.9.15) json_pure (1.4.6) mysql (2.8.1) 机架 (1.2.1) sqlite3-ruby (1.3.2) 薄(1.2.7) 雷神(0.14.1) tlee@tim-ubuntu:/media/dev/ruby-prax$ sqlite3 --version 3.6.22 tlee@tim-ubuntu:/media/dev/ruby-prax$

我做错了什么?

【问题讨论】:

    标签: ruby database sqlite dbi


    【解决方案1】:

    我遇到了同样的问题。当您多次使用准备好的 INSERT 语句时,有一个 issue on github 关于 DBD 的 SQLite 驱动程序失败。就个人而言,我已经接受了答案中的建议,即移至RDBI,因为 Ruby/DBI 显然不再被维护。迁移到 RDBI 只需要极少的代码更改。

    【讨论】:

    • 谢谢,我去看看。
    • RDBI 仍然是个好主意吗?那里似乎没有提交,但我不确定是因为项目被放弃还是因为几乎没有错误并且很少使用。
    【解决方案2】:

    你的表定义是:

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

    但您正在尝试插入:

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

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

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

    然后看看会发生什么。

    【讨论】:

    • 好接!但是,改了之后,并没有什么不同。我看到了完全相同的行为。事实上,对于 sqlite3,无论我将列定义为 varchar 还是 int,这个简单的插入似乎都没有太大区别。我尝试使用 slugs(name, age) 仍然遇到同样的错误。
    • 如果您尝试为“名称”传递数字,我希望它会给出相同的错误,因为这也是类型不匹配。 Name 必须是字符串,age 必须是整数/fixnum。
    • 在测试时调出数据库时可能看到的另一个错误是,如果您有一个字段的“distinct”或“unique”子句,则该字段仅限于独特的价值观。尝试重新运行尝试插入顺序值的代码将使数据库变得疯狂,从而在每次运行之前强制删除所有行。但我认为您没有使用“distinct”子句定义任何字段。
    • SQLite 将列类型视为提示,而不是执行严格的规则。 SQLite 网站上有 more information 介绍类型的工作原理。
    【解决方案3】:

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

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

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

    我在 SQLite3::Statement 类中没有看到 reset 和 clear 方法,所以这些方法可能会从这个实现中以某种方式遗漏,或者有一些其他机制可以在重用时自动重置/清除,但不知何故没有触发该机制.但是,文档中甚至没有提到它……至少我找不到它。

    我认为 SQLite3::Statement 类中缺少 clear_bindings 和 reset 方法。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 1970-01-01
      • 1970-01-01
      • 2019-03-07
      相关资源
      最近更新 更多