一直打算学习 ruby,奈何各种杂事,加上 perl 用的顺手,就此搁置。现在打定主意,今年一定要好好学学。花了两天时间看了入门教程,感觉 ruby 确实简洁,优雅,表现力强大。有了 perl 的基础,很多概念接受起来比较容易。平时主要跟数据库打交道,就从 DBI 入手开始学习吧。

ruby 的 DBI 总体使用同 perl 差不多,由于是纯粹面向对象,使用起来更为简洁。 

一、需要的模块
gem install -r dbi ruby-oci8

当然,需要先安装好 oracle client 。

二、先看一段基本代码

  1. require 'dbi'

  2. dbh = DBI.connect('dbi:OCI8:test','user','passwd') or exit;
  3. p dbh.driver_name

  4. dbh.select_all("select * from org where rownum) do |row|
  5.     # 结果分别以 hash ,array,string 展现
  6.     p row.to_h
  7.     p row.to_a
  8.     p row.to_s
  9.     
  10.     # 提取结果记录中某一字段,类型同数据库一致,空记录返回 nill
  11.     p row.by_field('ORG_NAME')
  12.     # 根据位置提取字段内容
  13.     p row.by_index(3)
  14.     
  15.     p row.object_id
  16.     p row.clone.object_id # 复制一条记录
  17.     p row.dup # 同 clone 一样
  18.     #p row.clone_with('') # 复制一条记录结构,用给定参数初始化
  19.     
  20.     row.each_with_name do |val, name|
  21.      printf "%-30s : %s \n", name, val.to_s
  22.     end
  23. end

  24. # 只提取第一条记录
  25. row = dbh.select_one("select * from org where rownum)
  26. p row

  27. dbh.disconnect
总体代码同 perl 差不多,基本步骤就是 :
dbi.connect
dbh.prepare 
sth.execute
sth.fetch
sth.finish
dbh.disconnect

三、DBI::ROW 解析
参考:http://ruby-dbi.rubyforge.org/rdoc/index.html

DBI::ROW 就是代表返回结果中的一条记录。如 sth.fetch 返回的结果就是 DBI::ROW 实例,让我们看看这个类里面有些什么:

1、to_a()
将返回结果转化成 array,格式如:[value1,value2,value3...]

源代码:
  1. # File lib/dbi/row.rb, line 87
  2.          def to_a
  3.              @arr.dup
  4.          end
例子: p sth.fetch.to_a

2、to_h()
将返回结果转化成 hash,格式如:{col1=>val1,col2=>val2,col3=>val3...}
通过 DBI::ROW.each_with_name 实现

源代码:
  1. # File lib/dbi/row.rb, line 92
  2.          def to_h
  3.              hash = {}
  4.              each_with_name{ |v, n| hash[n] = v}
  5.              hash
  6.          end
例子: p sth.fetch.to_h

补充:DBI::ROW 也实现了 to_s 方法,将结果转化成 String。

3、by_field(field_name)
根据字段名称,获取 row 对应字段的值。

源代码:
  1. # File lib/dbi/row.rb, line 117
  2. def by_field(field_name)
  3.     begin
  4.         @arr[@column_map[field_name.to_s]]
  5.     rescue TypeError
  6.         nil
  7.     end
  8. end
例子:
  1. sth.fetch do |row|
  2.      p row.by_field(org_name)
  3. end
2、by_index(index)

根据字段位置(0..n),获取 row 对应字段的值。
源代码:
  1. # File lib/dbi/row.rb, line 112
  2.         def by_index(index)
  3.             @arr[index]
  4.         end
例子:
  1. sth.fetch do |row|
  2.      p row.by_field(0)
  3. end
4、clone()dup()

克隆一条记录,dup 是 clone 的别名,两者等价。

源代码:
  1. # File lib/dbi/row.rb, line 92
  2.         def to_h
  3.             hash = {}
  4.             each_with_name{ |v, n| hash[n] = v}
  5.             hash
  6.         end
例子: new_row = sth.fetch.clone

5、clone_with(new_values)
克隆给定记录的结构,用 new_values 进行初始化。

源代码:
  1. # File lib/dbi/row.rb, line 100
  2.         def clone_with(new_values)
  3.             obj = Marshal.load(Marshal.dump(self))
  4.             obj.set_values(new_values)

  5.             return obj
  6.         end
例子:
6、convert_types(arr)
对返回结果进行类型变换

源代码:
  1. # File lib/dbi/row.rb, line 58
  2.         def convert_types(arr)
  3.             return arr.dup unless @convert_types

  4.             if arr.size != @column_types.size
  5.                 raise TypeError, "Type mapping is not consistent with result"
  6.             end
  7.             new_arr = []
  8.             arr.each_with_index do |item, i|
  9.                 new_arr.push((@column_types[i] || DBI::Type::Varchar).parse(item))
  10.             end

  11.             return new_arr
  12.         end

例子:

7、each_with_name() {|v, @column_names[i]| ...}

按键值对提取结果记录

源代码:
  1. # File lib/dbi/row.rb, line 80   
          def each_with_name
  2.              @arr.each_with_index do |v, i|
  3.                  yield v, @column_names[i]
  4.              end 
  5.          end
例子:
  1. sth.fetch.each_with_name do |v,k|
  2.      printf "%s --> %s\n",k,v
  3. end
可以参考 to_h() 源代码

8、set_values(new_values)

用 new_values 修改结果记录 ,此时也会对结果记录元素进行类型转换。

源代码:
  1. # File lib/dbi/row.rb, line 74
  2.         def set_values(new_values)
  3.             @arr.replace(convert_types(new_values))
  4.         end
例子: 




12-25 20:52