Chinaunix首页 | 论坛 | 博客
  • 博客访问: 398930
  • 博文数量: 69
  • 博客积分: 1984
  • 博客等级: 上尉
  • 技术积分: 953
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-28 00:43
个人简介

学无所长,一事无成

文章分类

全部博文(69)

文章存档

2015年(19)

2014年(14)

2013年(9)

2012年(17)

2010年(10)

我的朋友

分类: Python/Ruby

2012-02-20 22:01:01

一、本章开始学习 DBI::DatabaseHandle
通过 dbi.connect,我们可以获得一个 DBI::DatabaseHandle,就是我们常用的 dbh:
  1. dbh = DBI.connect('dbi:OCI8:test','user','passwd')
dbh 的主要方法有: commit、rollback; prepare、execute、do;select_one、 select_all;disconnect等。

二、 DBI::DatabaseHandle 解析
参考:

1、  --- 提交事务

源代码:
  1. # File lib/dbi/handles/database.rb, line 167
  2.         def commit
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             @handle.commit
  5.         end
在 dbi 初始化时需要关闭 AutoCommit;

示例:
  1. dbh['AutoCommit'] = false
    dbh.do("update test set name='xxx' ")
  2. dbh.commit

2、 --- 回滚事务
源代码;
  1. # File lib/dbi/handles/database.rb, line 175
  2.         def rollback
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             @handle.rollback
  5.         end
示例:
  1. dbh['AutoCommit'] = false
    dbh.do("update test set name='xxx' ")
  2. dbh.rollback
3、 
一般用于执行 update、delete、insert、drop table、truncate table、alter table 等无需返回值的sql,返回值为变动或被修改记录数量。

源代码:
  1. # File lib/dbi/handles/database.rb, line 94
  2.         def do(stmt, *bindvars)
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             @handle.do(stmt, *DBI::Utils::ConvParam.conv_param(driver_name, *bindvars))
  5.         end
4、

准备一条 sql ,返回  ,就是前文学习的 DBI::StatementHandle,一般用 sth 表示。如果后面跟一个 block ,则将 sth 作为参数,代码块结束后会调用 finish ,这样代码会非常紧凑。

源代码:
  1. # File lib/dbi/handles/database.rb, line 47
  2.         def prepare(stmt)
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             sth = StatementHandle.new(@handle.prepare(stmt), false, true, @convert_types)
  5.             # FIXME trace sth.trace(@trace_mode, @trace_output)
  6.             sth.dbh = self

  7.             if block_given?
  8.                 begin
  9.                     yield sth
  10.                 ensure
  11.                     sth.finish unless sth.finished?
  12.                 end
  13.             else
  14.                 return sth
  15.             end
  16.         end
示例:
程序结构看上去赏心悦目,比 perl 漂亮;其实我们可以再简化啦,就是用 execute
  1. dbh = DBI.connect('dbi:OCI8:test','user','passwd')
  2. dbh.prepare('select * from test') do |sth|
  3.     sth.execute
  4.     sth.fetch do |row|
  5.         p row
  6.     end
  7. end
5、execute(stmt, *bindvars) {|sth| ...}
就是整合了 dbh.prepare 和 sth.execute ;同样后面可以跟 block。

源代码:
  1. # File lib/dbi/handles/database.rb, line 67
  2.         def execute(stmt, *bindvars)
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?

  4.             if @convert_types
  5.                 bindvars = DBI::Utils::ConvParam.conv_param(driver_name, *bindvars)
  6.             end

  7.             sth = StatementHandle.new(@handle.execute(stmt, *bindvars), true, false, @convert_types)
  8.             # FIXME trace sth.trace(@trace_mode, @trace_output)
  9.             sth.dbh = self

  10.             if block_given?
  11.                 begin
  12.                     yield sth
  13.                 ensure
  14.                     sth.finish unless sth.finished?
  15.                 end
  16.             else
  17.                 return sth
  18.             end
  19.         end

示例:我们可以舍弃 execute 了。
  1. dbh = DBI.connect('dbi:OCI8:test','user','passwd')
  2. dbh.prepare('select * from test') do |sth|
  3.     sth.fetch do |row|
  4.         p row
  5.     end
  6. end
如果只是简单的获取结果,我们可以使用 select_one 跟 select_all

6、
相当于整合了 dbh.execute、sth.fetch_all ;如果后面跟了一个 block ,则对每条记录进行遍历。

源代码:
  1. # File lib/dbi/handles/database.rb, line 115
  2.         def select_all(stmt, *bindvars, &p)
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             rows = nil
  5.             execute(stmt, *bindvars) do |sth|
  6.                 if block_given?
  7.                     sth.each(&p)
  8.                 else
  9.                     rows = sth.fetch_all
  10.                 end
  11.             end
  12.             return rows
  13.         end
代码中调用 sth.each 执行 block ,结合前文中 DBI::StatementHandle each 的分析,可以看出,传入 block 处理数据,本质上是打开一个循环,逐条 fetch 数据后处理。因此当处理巨量数据时, select_all 最好跟上 block 进行处理,否则会消耗大量内存。

示例:
  1. dbh = DBI.connect('dbi:OCI8:test','user','passwd')
  2. dbh.select_all('select * from test') do |row|
  3.     p row
  4. end

7、  

同 select_all 差不多,区别在于只取一条记录。

源代码
  1. # File lib/dbi/handles/database.rb, line 102
  2.         def select_one(stmt, *bindvars)
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             row = nil
  5.             execute(stmt, *bindvars) do |sth|
  6.                 row = sth.fetch
  7.             end
  8.             row
  9.         end

8、  

  1. # File lib/dbi/handles/database.rb, line 159
  2.         def quote(value)
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             @handle.quote(value)
  5.         end
9、  

  1. # File lib/dbi/handles/database.rb, line 151
  2.         def ping
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             @handle.ping
  5.         end
10、  

开启一个事务,执行其后的代码块,成功则提交,失败则回滚。
  1. # File lib/dbi/handles/database.rb, line 185
  2.         def transaction
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             raise InterfaceError, "No block given" unless block_given?

  5.             commit
  6.             begin
  7.                 yield self
  8.                 commit
  9.             rescue Exception
  10.                 rollback
  11.                 raise
  12.             end
  13.         end
11、  

提供一个表名,返回该表字段信息,返回值是元素为    的数组。
源代码:
  1. # File lib/dbi/handles/database.rb, line 141
  2.         def columns( table )
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             @handle.columns( table ).collect {|col| ColumnInfo.new(col) }
  5.         end

12、  

返回该   句柄下的所有表,返回值为字符串数组。
源代码:
  1. # File lib/dbi/handles/database.rb, line 131
  2.         def tables
  3.             raise InterfaceError, "Database connection was already closed!" if @handle.nil?
  4.             @handle.tables
  5.         end

....


阅读(1279) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~