使用Ruby的MySql模塊(1)

 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

簡介

想想php當時爲什麼這麼流行,一點原因就是因爲有了Mysql這個天生的搭檔。現在,mysql幾乎是opensource裏用的最多的數據庫了。在Ruby裏,可以通過Tomita  Masahiro MySQL模塊,它提供了一個供Ruby使用的客戶端api,其實就是對mysql c API的包裝。

本文主要要講mysql模塊的安裝,編寫基於Rubymysql的腳本程序。

       翻譯整理:http://www.ruby-cn.org/

安裝MySQL模塊

 

要想用Ruby的MySQL模塊,你要先確保你的MySQL C客戶端API頭文件和庫文件已經成功安裝,這是必須的,因爲mysql 模塊是基於這個寫的。

首先從http://www.tmtm.org/en/mysql/ruby/ 下載軟件包,然後解壓縮,比如:

% tar zxvf mysql-ruby-2.4.4a.tar.gz

然後進入到解壓縮之後的頂層目錄,開始configure(ruby特有的方式)。

% ruby extconf.rb

extconf.rb會自動檢查mysql頭和庫文件,如果找到了,你可以直接進行下一步,如果沒找到,需要手動填寫參數,比如:

% ruby extconf.rb /

--with-mysql-include=/usr/local/mysql/include/mysql /

--with-mysql-lib=/usr/local/mysql/lib/mysql

假設mysql的頭和庫文件分別如上面所示的那樣。

 

上述操作成功之後,就可以運行make了

% make

% make install(用root運行)

 

 

MySQL模塊概覽

 

MySQL模塊包括4個類:

  • Mysql

主類,提供了諸如連接數據庫,發送查詢語句,管理操作等功能。

• MysqlRes

結果集類,用來產生查詢得到的結果。

• MysqlField

Metadata類,它包含結果集中字段的信息,比如字段名,類型,大小等。

• MysqlError

異常類,當其他三個類出現錯誤時,要用的到。

 

因爲大體上來說mysql模塊是對mysql c API的包裝,所以它的函數名字也是有規律的,比如c api的函數名是mysql_real_connect(),在Ruby裏,就是real_connect(),可以看出,就是去掉了前面的mysql_前綴。

 

第一個簡單例子

 

首先確保我們在本地數據庫有一個數據庫叫rubydb,一個用戶test,密碼也是test。

例子如下:

# file name : example1.rb

 

require "mysql"

begin

# connect to the   server

dbh = Mysql.real_connect("localhost", "test", "test", "rubydb")

# get server version string and display it

puts "Server version: " + dbh.get_server_info

rescue MysqlError => e

print "Error code: ", e.errno, "/n"

print "Error message: ", e.error, "/n"

ensure

# disconnect from server

dbh.close

end

 

現在來看一下這個程序:

第一行,包含了mysql模塊,告訴ruby把mysql模塊引入。

Real_connect函數鏈接數據庫,四個參數都很容易理解。其實,mysql模塊還提供了一些別名,比如new,connect和real_connect是等同的。

Dbh(database handle)用來和mysql交互,比如例子中調用get_server_info函數取得服務器相關信息,比如版本。

Begin . . . rescue . . . ensure . . . 是異常處理中講過的東西,類似java的try catch finally機制。如果dbh在與數據庫交互工程中出錯,則被rescue捕獲,並賦給e指向一個MysqlError的異常,這個異常包括兩個只讀屬性:errno,錯誤編號,整數,error,錯誤消息,字符串型。

如果這個程序執行正確,不出錯誤,結果如下:

% ruby example1.rb

Server version: 4.0.12-log

如果執行出錯,比如我們寫了一個錯誤的主機名,把localhost寫成loclahost,則會出錯:

% ruby example1.rb

An error occurred

Error code: 2005

Error message: Unknown MySQL Server Host ’ loclahost’ (1)

 

處理查詢

我們暫且把sql分爲兩類:dml,ddl(這個不要深究)。Ddl包括create,insert,update,delete;dml包括select,show等。Ddl不需要返回結果集,所以很容易處理;dml需要返回結果集,需要多一些處理過程。

1.對於不需要返回結果集的語句調用query方法就行,如果想知道受影響的行數,可以用affected_rows得到。綜合例子如下:

dbh.query(“drop table test”)

dbh.query(“create table test

id int,

name char(20)

”)

dbh.query(“insert into test valuse(1,’name1’)”)

printf "%d rows were inserted/n", dbh.affected_rows

 

2.對於需要返回結果的查詢,比如select,需要遵循如下過程:

a.                調用query方法向數據庫發送查詢請求,並得到一個結果集(MysqlRes的一個實例),這個結果集提供了取一行,移動,取得列的元數據(metadata)等方法。

b.                fetch_row等函數或者迭代等處理每一行數據。

c.                如果你想知道總共返回多少行,可以用num_rows方法。

d.                別忘了最後用free釋放結果集對象。

 

res = dbh.query("SELECT id,name FROM test1")

 

while row = res.fetch_row do

printf "%s, %s/n", row[0], row[1]

end

 

printf "%d rows were returned/n", res.num_rows

res.free

或者用迭代:

res = dbh.query("SELECT id,name FROM test1")

res.each do |row|

printf "%s, %s/n", row[0], row[1]

end

printf "%d rows were returned/n", res.num_rows

res.free

fetch_row 和each 每次都返回一個數組,下標爲0的元素表示第一個列的數據等。此外,還可以用fetch_hash方法,返回一個hash結構,即類似java裏Map的key-value結構:

res = dbh.query("SELECT id,name FROM test1")

while row = res.fetch_hash do

printf "%s, %s/n", row["id"], row["name"]

end

printf "%d rows were returned/n", res.num_rows

res.free

 

each_hash是each的哈希版本:

res = dbh.query("SELECT id,name FROM test1")

res.each_hash do |row|

printf "%s, %s/n", row["id"], row["name"]

end

printf "%d rows were returned/n", res.num_rows

res.free

 

默認的時候,哈希中key的值就是列名,但是如果選擇的列有重名的時候,這可能會帶來很多問題,比如下面的語句中的兩個字段都叫做i:

SELECT t1.i, t2.i FROM t1, t2;

如果你用哈希結構來取,只能取得一列的值。爲了解決這種列名衝突問題,你可以在fetch_hash或者each_hase的時候指定with_table=true,這樣,哈希德key就是表明和類名連在一塊的值了,格式就是tbl_name.col_name。

 

 

res = dbh.query("SELECT id, name FROM animal")

 

res.each_hash(with_table = true) do |row|

printf "%s, %s/n", row["test.id"], row["test. name"]

end

 

printf "%d rows were returned/n", res.num_rows

res.free

 

如果在查詢語句裏對錶或者列名用了別名,那麼這些別名將作爲哈希裏的key值,而不是原來的表名和列名。

fetch_row,each,我們必須記住每個字段的位置,才能準確的找到他,這對select * 查詢來說比較困難。而用fetch_hash 和 each_hash責可以避免這種情況,可以根據列名來取列值,而不必去管列的位置如何。

如果指定了參數with_table=true,而查詢的字段中還有表達式,那麼,對應這些表達式的key值中前面的tbl_name部分將是空的(但是”.”還在),比如你有如下查詢:

SELECT i, i+0, VERSION(), 4+2 FROM t;

只有I是表的列名,其他都是表達式,那麼這些列對應於哈希表中的key值分別是: "t.i", ".i+0", ".VERSION()",和 ".4+2".

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章