这是我的方法
def convertElsToMass(symbol)
begin
db = SQLite3::Database.open("test.db")
rs = db.prepare("SELECT * FROM Elements WHERE symbol = '#{symbol} '")
temp = rs.execute
mass = temp.first
rescue SQLite3::Exeption => e
puts e
ensure
db.close if db
end
return mass[3]
end
当我使用rspec测试此方法时,出现此错误消息:
1) PeriodicTable should change Elements to mass of Elements
Failure/Error: expect(table.convertElsToMass("Na")).to eq(22.9898)
SQLite3::BusyException:
unable to close due to unfinalized statements or unfinished backups
# ./lib/formatel.rb:42:in `close'
# ./lib/formatel.rb:42:in `convertElsToMass'
# ./spec/lib/pt_spec.rb:13:in `block (2 levels) in <top (required)>'
我注意到如果我不放行db.close if db
这个方法完全符合我的预期。但是,我担心在执行查询后如果不关闭数据库会产生什么后果。我如何解决这个问题,以便在执行查询后关闭数据库?
答案 0 :(得分:1)
您无需担心关闭数据库。当您拨打prepare
或execute
时,这些呼叫会在完成后自动呼叫关闭。有一个内部rescue/ensure
块,可确保即使出现错误也会关闭数据库。您可以在SQLite3::Database的源代码中看到这一点。
答案 1 :(得分:0)
很晚了,但让我回答您的问题并提出解决方案:
不要为sqlite3关闭数据库
这取决于代码运行多长时间以及在所述运行时期间打开数据库的次数。如果经常发生这种情况,那么您将用完允许打开的文件描述符(在大多数Linux发行版中通常为1024)。因此(显然是为了防止内存问题),您应该始终关闭数据库,尤其是当您打算长时间运行脚本时。
此问题的解决方法是您必须完成SQLite语句(请参见sqlite_finalize)。在ruby的sqlite3中,您可以通过在语句中调用.close
来实现此目的。
因此,在您的代码中,在temp = rs.execute
之后,您只需要添加一个rs.close
即可关闭并完成该语句。语句关闭后,您的数据库将不再忙碌,您可以关闭它。