2010-11-23 78 views
2

在我學習Ruby的嘗試中,我一直在閱讀Mr. Neighborly's Humble Little Ruby Book爲什麼我的簡單Ruby SQLite3示例失敗?

大多數的例子已經很容易跟着給我一個很好的介紹,紅寶石,但我不能很容易地運行數據庫相關的例子。

我試圖運行此代碼:(從書中給出的例子稍作修改)

#!/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上。 版本信息:

 
[email protected]:/media/dev/ruby-prax$ ruby -v 
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux] 
[email protected]:/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) 
[email protected]:/media/dev/ruby-prax$ sqlite3 --version 
3.6.22 
[email protected]:/media/dev/ruby-prax$ 

我在做什麼錯?

回答

1

您的表的定義是:

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

但您嘗試插入:

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

注意"#{i}"不是整數,這是一個字符串。將其更改爲i,如下例所示:

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

然後看看會發生什麼。

+0

好拿起!但是,在改變它之後,它沒有任何區別。我看到完全一樣的行爲。實際上,對於sqlite3而言,無論我將列定義爲varchar還是int,對於這個簡單插入來說都沒有太大區別。我嘗試與slu((名字,年齡),仍然有同樣的錯誤。 – 2010-11-23 10:53:09

+0

我希望它會給出同樣的錯誤,如果您嘗試傳遞「名稱」的數字,因爲這也是類型不匹配。名稱必須是一個字符串,並且年齡必須是整數/修訂號。 – 2010-11-23 16:39:38

2

我遇到了同樣的問題。有一個issue on github關於多次使用準備好的INSERT語句時DBD失敗的SQLite驅動程序。就我個人而言,我在回答那裏的建議時轉向RDBI,因爲Ruby/DBI顯然不再被維護。轉向RDBI需要非常少的代碼更改。

0

不知何故,我認爲Ruby的幾個sqlite3的庫丟失復位並聲明類明確的方法。

當相同的SQL語句被重複執行時,一個語句被準備一次並用一組新的值執行。但是在聲明執行之後並且在重新綁定之前,它需要被重置(並且通常被清除)。重點在於重置已使用的語句比重複「編譯和優化」同一SQL更快。大多數人可能知道這一切......但這裏的鏈接到相關部分的SQLite的文檔:

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

我沒有看到重置和sqlite3的::類Statement明確方法,因此這些可能在某種程度上錯過了這個實現,或者有一些其他機制在重用時自動重置/清除,但是該機制在某種程度上不會被觸發。但是,它甚至沒有在文檔中提到......至少我找不到它。

我認爲clear_bindings和重置方法從SQLite3 :: Statement類中缺少。

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

相關問題