以下是我使用DBI的示例代码:
dbh = DBI.connect("DBI:Mysql:host=#{server};database=mysql", user, pass)
rows = dbh.select_all("SHOW TABLES")
这里的行打印如下:
[["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"],
["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"], ["user"],
["user"]]
这是打印mysql数据库中的最后一个表,但记录总数是正确的。
如果我使用execute-fetch / each-finish序列执行此操作,如下所示:
sth = dbh.execute("SHOW TABLES")
sth.each do |row|
rows << row[0]
end
sth.finish
但它给了我正确的结果,如:
["columns_priv", "db", "func", "help_category", "help_keyword", "help_relation",
"help_topic", "host", "proc", "procs_priv", "tables_priv", "time_zone", "time_z
one_leap_second", "time_zone_name", "time_zone_transition", "time_zone_transitio
n_type", "user"]
帮我解决这个问题?
答案 0 :(得分:2)
使用DBI.connect("DBI:ODBC:Driver={SQL Server};...")
我的工作是强制将DBI :: Row转换为数组:
sth = dbh.execute "..."
begin
return sth.map{ |row| row.to_a }
ensure
sth.finish
end
我敢打赌1000美元的问题与缓冲区重用有关 - 一种可能的“性能”增强,它具有不可抗拒的副作用!
答案 1 :(得分:1)
我猜dbh.select_all
返回一个Enumerator实例,它在每次迭代时产生相同的行。看到这个伪代码来理解我的意思:
def select_all(query)
db_row = Row.new
reader = @connection.execute_reader(query)
Enumerator.new do |yielder|
until reader.end?
db_row.populate_from(reader)
yielder.yield db_row
reader.next!
end
end
end
因此,如果你在没有块的情况下使用select_all,将返回一个枚举器,它基本上产生相同的db_row对象。
这只是猜测,但我相信事实就在附近。
UPD:这里的源代码https://github.com/erikh/ruby-dbi/blob/master/lib/dbi/handles/statement.rb(请参阅获取方法定义)说我错了,因为@row
在每次迭代时都是dup
。好吧,可能错误就在堆栈的某个地方......