Ruby DBI モジュールを使う

Paul DuBois
paul@kitebird.com
訳者
久保健洋
kubo@jiubao.org

Original Document revision: 1.02
Original Last update: 2003-05-27
翻訳バージョン: 0.9

目次


はじめに


Ruby DBI モジュールは Perl DBI と同様にデータベースに依存しないインター フェースをRubyスクリプトへ提供します。この記事では Ruby DBI を使用した スクリプトの書き方を説明します。これは DBI 仕様書を補助するものであっ て置き換えるものではありません。DBI仕様書は必ず読んでください。さらな る情報を得たいときは「リソース」セクションを読んでください。

Ruby DBI のアーキテクチャは一般的に2つの層(レイヤ)を使用します。

この記事では MySQL データベースドライバを例にとります。しかしほとんど のことは他のドライバでも同様に使うことができます。

前準備

Ruby DBIモジュールは汎用的なDBI層のコードとDBDレベルのドライバ を含んでいます。これらのドライバを使用するためにはほとんどの場合、追加 のソフトウェアをインストールする必要があります。例えば MySQL のデータ ベースドライバは Ruby で書かれていて、Ruby MySQLモジュールとの橋わたし を行います。そして、C で書かれた Ruby MySQL モジュールが、MySQL の Cク ライアントライブラリとの橋わたしを行います。この意味するところは、 DBI スクリプトを書いて MySQL データベースへ接続したいのならば、Ruby MySQL モジュールと C API との両方ともをインストールする必要があるとい うことです。Ruby MySQL モジュールについてのさらなる情報は「リソース」セ クションで参照している記事を見てください。ここでは MySQL モジュールは インストールされ、使用できる状態にあると仮定します。

インストール

ひとつ前のセクションで説明した前準備が終わったら、Ruby DBI モジュール のインストールが可能となります。Ruby DBI モジュールは以下のサイトから 取得できます。

   http://ruby-dbi.sourceforge.net/

DBIモジュールは圧縮されたtarファイルとして配布されているので、ダウン ロードした後に展開する必要があります。例えば、現在のバージョンが 0.0.19 とすると、配布ファイルは以下のコマンドで展開されます。
   % tar zxf ruby-dbi-all-0.0.19.tar.gz
   (訳者註: GNU tar の場合)
   % gunzip < ruby-dbi-all-0.0.19.tar.gz | tar xf -
   (訳者註: 商用UNIXのOS附属の tar の場合)
配布パッケージを展開したら、展開したファイルのトップディレクトリへ移動し、 そのディレクトリにある setup.rb スクリプトを使って設定処理を行います。 もっとも一般的な設定コマンドは以下のように config 引数の後にはなにも 引数をつけません。
   % ruby setup.rb config
このコマンドは、デフォルトではすべてのドライバをインストールする ように配布パッケージの設定を行います。もっと詳細に設定したい 場合は、--with オプションに使用したいドライバ用の名前を列挙します。 例えば、DBI のメイン部分と MySQL の DBD レベルのドライバのみを設 定するときは、次のコマンドを発行します。
   % ruby setup.rb config --with=dbi,dbd_mysql
配布パッケージの設定をしたら、ビルドしてインストールします。
   % ruby setup.rb setup
   % ruby setup.rb install
root ユーザで実行する必要があるかもしれません。

この記事では以降、以下の表記を慣習として使用します。

単純なDBIスクリプト

Ruby DBI モジュールをインストールされている状態になったら、Rubyプログ ラムから MySQL サーバは接続できるようになっているはずです。 この記事では、サーバはローカルホストで動いており、test という名前のデー タベースへ testuser、testpass というユーザ名、パスワードで接続できると いう仮定をします。testuser を作成するには、MySQL の root ユーザでサー バへ接続して次の文を発行してください。

   mysql> GRANT ALL ON test.* TO 'testuser'@'localhost' IDENTIFIED BY 'testpass';
test データベースがない場合は、次の文を発行してデータベースを作成して ください。
   mysql> CREATE DATABASE test;
別のサーバホスト、ユーザ名、パスワード、データベース名を使用したい場合 は、この記事の以降のスクリプトにでてくる値を適切な値に置き換えてくださ い。

次のスクリプトsimple.rbは、サーバへ接続して、サーバのバージョン を取得して、表示して、接続を切るだけの短いDBIプログラムです。このスク リプトは「リソース」セクションのリンクからダウンロードできます。または テキストエディタで直接作成しても良いでしょう。

   # simple.rb - Ruby DBI を使用した簡単なMySQLスクリプト

   require "dbi"

   begin
       # MySQLサーバへ接続
       dbh = DBI.connect("dbi:Mysql:test:localhost", "testuser", "testpass")
       # サーババージョンの文字列を取得して、表示する。
       row = dbh.select_one("SELECT VERSION()")
       puts "Server version: " + row[0]
   rescue DBI::DatabaseError => e
       puts "An error occurred"
       puts "Error code: #{e.err}"
       puts "Error message: #{e.errstr}"
   ensure
       # サーバから切断
       dbh.disconnect if dbh
   end

simple.rbスクリプトからはDBIの基本的なコンセプトが読み取れます。 すぐ次に続く議論ではDBIがどのように働くかを説明し、その後のセクション ではDBIプログラミングに特有の側面について詳細に読み取れる例を示します。

simple.rbはDBIモジュール要求するをrequireの行から始ま ります。この行がないと、DBI メソッド呼び出しが失敗します。スクリプトの 残り部分はbegin/rescue/ensureの中に置いてあります。

connectメソッドはデータベースサーバへの接続を確立し、サーバと の通信に使用するデータベースハンドルを戻します。第一引数には、ドライバ 名(MySQLの場合はMysql)、デフォルトのデータベース名、サーバの ホスト名を示すデータソース名(DSN, data source name)をわたします。 第二引数と第三引数は MySQL アカウントのユーザ名とパスワードです。DSNの 値を書く方法は他にもあり、その方法は「サーバへの接続」セクションで後述 されます。

simple.rbはデータベースハンドルを使ってselect_oneメソッ ドを呼んでいます。このメソッドは、問い合わせをサーバへ送り、結果列の最 初の行を配列として戻すメソッドです。問い合わせSELECT VERSION()は値をひとつ戻します。したがって、バージョン文字列は row[0]として利用できます。これは配列の最初のそして唯一の項目 です。スクリプトを走らせると、結果はこのように見えます。

   % ruby simple.rb
   Server version: 4.0.13-log
エラーが起こると例外が上ります。様々な種類の例外が起こり得ます。 しかし、データベースの操作に関するエラーのほとんどは DatabaseError例外を引き起こします。この例外のオブジェクトは errerrstrの属性を持っていて、エラー番号とエラーの 内容を記述したメッセージを意味します。 simple.rbはデータベース例外に関連するこれらの値を取得して出力 し、その他の種類の例外は無視します。(別の例外を上げて、rubyそのものが 処理できるように戻すべきです。)

simple.rbdisconnectメソッドを呼んでサーバへの接続を 切ります。切断はensureブロックで行い、問い合せを処理している 最中にエラーが起きても確実に接続が終了するようにします。

問合せ処理


RUby DBI はSQL文を実行するのに何種類も方法があります。このセクションで はそのうちのいくつかを論じます。SQL文を実行方法は他にもいくつもありま す。

ほとんどの例では、peopleという名前のテーブルそ使用します。こ のテーブルは以下の構造をしています。

   CREATE TABLE people
   (
       id INT UNSIGNED NOT NULL AUTO_INCREMENT,    # ID番号
       name CHAR(20) NOT NULL,                     # 名前
       height FLOAT,                               # 身長(インチ単位)
       PRIMARY KEY (id)
   );

結果セットを返さない問合せ処理

行を返さないSQL文の発行は、データベースハンドルのdoメソッドの 呼び出しで行うことができます。このメソッドは問い合せ文字列1つを引数にと り、問い合わせで影響の受けた行を戻します。次の例はdoを何回も 使用して、peopleテーブルを作成し小さなデータのあつまりを生成 します。

   dbh.do("DROP TABLE IF EXISTS people")
   dbh.do("CREATE TABLE people (
           id INT UNSIGNED NOT NULL AUTO_INCREMENT,
           PRIMARY KEY (id),
           name CHAR(20) NOT NULL,
           height FLOAT)")
   rows = dbh.do("INSERT INTO people (name,height)
           VALUES('Wanda',62.5),('Robert',75),('Phillip',71.5),('Sarah',68)")
   printf "%d rows were inserted\n", rows
INSERT文の実行では、行数を取得して表示しています。行数はどれ だけの数の行がテーブルに追加されたかを表わします。

結果セットを返す問合せ処理


SELECTSHOWといったSQL文は行を戻します。このような SQL文を処理するには、SQL文をサーバへ送信して実行し、生成された結果セッ トに含まれる行を取得して、最後に結果セットを破棄します。

これを実行する方法のひとつは、prepareメソッドを呼んで文ハンド ルを生成することです。このハンドルを使用して文を実行し、結果を得て、結 果セットを解放します。

   sth = dbh.prepare(SQL文)
   sth.execute
   ... 行を取得 ...
   sth.finish
直接SQL文をexecuteにわたして、prepareの呼び出しをス キップすることも可能です。
   sth = dbh.execute(SQL文)
   ... 行を取得 ...
   sth.finish
SQL文を実行した後に結果を得る方法はいろいろあります。fetchを ブロックなしで呼び出しで、nilが戻るまでループする方法がありま す。
   sth = dbh.execute("SELECT * FROM people")
   while row = sth.fetch do
       printf "ID: %d, Name: %s, Height: %.1f\n", row[0], row[1], row[2]
   end
   sth.finish
fetchはイテレータとしても使うことができます。これは eachをイテレータとして呼んだときと同じです。これらの2つの行 取得ループは同じものです。
   sth = dbh.execute("SELECT * FROM people")
   sth.fetch do |row|
       printf "ID: %d, Name: %s, Height: %.1f\n", row[0], row[1], row[2]
   end
   sth.finish

   sth = dbh.execute("SELECT * FROM people")
   sth.each do |row|
       printf "ID: %d, Name: %s, Height: %.1f\n", row[0], row[1], row[2]
   end
   sth.finish
fetcheachDBI::Rowオブジェクトを生成し、 このオブジェクトのメソッドでもって、その中身にアクセスできます。 その他の行を取得するメソッドは、fetch_arrayfetch_hash があります。このメソッドはDBI::Rowオブジェクトを戻しません。 代りに次の行を配列やハッシュとして戻し、それ以上行がないときはnilを戻 します。fetch_hashで戻るハッシュはカラム名がキーでカラムの値 が値となっています。どちらのメソッドもブロックなしでも、イテレータとし ても呼ぶことができます。次はfetch_hashを使用した例を表してい ます。
   sth = dbh.execute("SELECT * FROM people")
   while row = sth.fetch_hash do
       printf "ID: %d, Name: %s, Height: %.1f\n",
               row["id"], row["name"], row["height"]
   end
   sth.finish

   sth = dbh.execute("SELECT * FROM people")
   sth.fetch_hash do |row|
       printf "ID: %d, Name: %s, Height: %.1f\n",
               row["id"], row["name"], row["height"]
   end
   sth.finish
データベースハンドルのメソッドを利用して、execute-fetch-finishの一連の 操作を回避することができます。次のメソッドはこれらの仕事を代りに行い、 結果を戻します。
   row = dbh.select_one(statement)
   rows = dbh.select_all(statement)
select_oneは問合せを実行して最初の一行を配列として戻します。 問合せが一行も返さないときはnilを戻します。 select_allDBI::Rowオブジェクトの配列を戻します。 (このオブジェクトの中身は以前説明したようにアクセスできます。) 問合せが一行も返さないときは空の配列となります。

MySQLドライバは結果セットのメタデータを調べて行の値を対応するRubyのデー タタイプへ変換します。(これが意味することは、例えば、people テーブルから取り出されたidnameheightの 値がFixnumStringFloatのオブジェクトとし て戻されるということです。) しかし、カラムの値がNULLの場合は 注意してください。この場合は、NULL値は結果セットではnilとして 表現され、その種類はNilClassとなります。また、この変換の挙動 は見たところDBI仕様書では規定されてなくて、すべてのドライバでこのよう に変換されるとは限らないことに注意してください。

クオート、プレースホルダー、パラメータ束縛

Ruby DBI にはプレースホルダー機構があり、問合せ文字列のデータの 値を直接取り込まなくても良いようになっています。代わりにSQL文の中に特 別な印をつけて、データの値が入る場所を示します。SQL文を実行するときに は、プレースホルダーにバインドする値を与えておきます。DBIはプレースホ ルダーの現れる場所のSQL文をバインドした値に置き換えます。このとき文字 列の値はクオートで囲って、必要なら特殊文字をエスケープします。これを使 うと、与えようとする文字に特殊文字が含まれているかどうか気にせずに、ま た、自身でクオートで囲うことなしに簡単にSQL文を組み立てることができま す。プレースホルダー機構はNULL値も適切にあつかいます。 nilをデータとして与えるだけで、クオートされていない NULL値としてSQL文中に置かれます。

次の例はこれがどのように働くかを説明します。例として、クオートを含む Na'ilという名前で身長が76インチの人をpeopleテーブルにに追加す ると想定しましょう。まず、データがINSERT文のどこに入るかを示 すために、プレースホルダーの印'?'を(シングルクオートなしで)使 い、次いで、doの引数にSQL文につづけて、追加の引数としてデータ を与えます。

   dbh.do("INSERT INTO people (id, name, height) VALUES(?, ?, ?)",
           nil, "Na'il", 76)
doにより生成されてサーバへ送られる最終的なSQL文は次のようにな ります。
   INSERT INTO people (id,name,height) VALUES(NULL,'Na\'il',76)
SQLを何回も実行しようと考えている場合は、文ハンドルを得るために prepareで準備してから、executeでデータを引数として与 えながら実行することができます。 people.txtという名のデータファイルに、peopleテーブルに挿 入する名前/身長のペアがタブ区切りで行毎にはいっていると仮定しましょう。 次の例はファイルを呼んで一行のデータを得て、前もって準備した INSERT文を各行ごとに実行します。
   # 挿入ループで使用する文ハンドルを用意する。
   sth = dbh.prepare("INSERT INTO people (id, name, height) VALUES(?, ?, ?)")

   # ファイルから一行づつ読んで、値に分けて、データベースへ挿入する。
   f = File.open("people.txt", "r")
   f.each_line do |line|
       name, height = line.chomp.split("\t")
       sth.execute(nil, name, height)
   end
   f.close
最初のSQL文を準備してからループ内で何回も実行することは、ループ毎に doを呼び出す(繰り返し毎にprepareexecuteの 両方を呼ぶのと同等)よりも効率的です。問い合わせ実行計画を準備して、 executeの呼び出し毎に実行計画を再利用するデータベースの場合、 これは重大な効率上の差異となります。MySQLは実行計画を再利用はできませ んが、Oracleは再利用します。

SELECT文にプレースホルダーを使う場合、SQL文を最初の準備するか にするかどうかで適切な方法がかわります。

他のドライバは別の形式のプレースホルダーでも受け付けるかもしれません。 また、別の形式でないと受け付けないかもしれません。例えば、プレースホル ダーを :name:n として名前付きや数値付きの形式で 書けるかもしれません。

quoteメソッドはデータ値をクオートで囲い、特殊文字をエスケープ して、結果を戻します。これは他のプログラムで実行するSQL文を組み立てる のに便利です。例えば、データファイルpeople.txtを読んで、 INSERT文のかたまりに変形して、コマンドラインクライアントの mysqlといったプログラムで処理させる場合、次のようにします。

   # ファイルから一行づつ読んで、値に分けて、INSERT文を書き出す。
   f = File.open("people.txt", "r")
   f.each_line do |line|
       name, height = line.chomp.split("\t")
       printf "INSERT INTO people (id, name, height) VALUES(%s, %s, %s);\n",
               dbh.quote(nil), dbh.quote(name), dbh.quote(height)
   end
   f.close

メタデータの問い合わせ

INSERTDELETEといった結果セットを戻さないSQL文の場 合、doメソッドは処理された行数を戻します。

SELECTといった行を戻すSQL文の場合、executeを呼んだ後 に文ハンドルを使い、結果セットの行数やカラム数、個々のカラムの情報を得 ることができます。

次のスクリプトは問い合わせからメタデータを得る方法を示します。
   sth = dbh.execute(query)

   puts "問い合わせ: " + query
   if sth.column_names.size == 0 then
       puts "問い合わせには結果セットがありません。"
       printf "影響を受けた行の数: %d\n", sth.rows
   else
       puts "問い合わせには結果セットがあります。"
       rows = sth.fetch_all
       printf "行数:     %d\n", rows.size
       printf "カラム数: %d\n", sth.column_names.size
       sth.column_info.each_with_index do |info, i|
           printf "--- カラム %d (%s) ---\n", i, info.name
           printf "精度:     %s\n", info.precision
           printf "スケール: %s\n", info.scale
       end
   end
   sth.finish
注意事項: 古いバージョンのこの文書では、SELECT文の結果の行数 をsth.rowsで得ることができると述べていましたが、これはサポー トされていません。(現在のところ MySQL ドライバではたまたま動きますが、 この挙動は信頼しないでください。)

コードブロックつきのメソッド


ハンドルを生成するメソッドのうちいくつかはコードブロック付きで呼ぶこと ができます。ブロック付きで実行した時、ハンドルはコードブロックのパラメー タとして渡され、ブロックの実行が終了したら自動的にハンドルが解放されま す。

これらのハンドルを生成するメソッドそれぞれに対してコードブロックを使っ た例です。
   # connectはコードブロックをとり、データベースハンドルをブロックに渡します。
   # ブロックの最後では自動的にハンドルを切断します。

   DBI.connect("dbi:Mysql:test:localhost", "testuser", "testpass") do |dbh|

       # prepareはコードブロックをとり、文ハンドルをブロックに渡します。
       # ブロックの最後では自動的にfinishを呼びます。

       dbh.prepare("SHOW DATABASES") do |sth|
           sth.execute
           puts "Databases: " + sth.fetch_all.join(", ")
       end

       # executeはコードブロックをとり、文ハンドルをブロックに渡します。
       # ブロックの最後では自動的にfinishを呼びます。

       dbh.execute("SHOW DATABASES") do |sth|
           puts "Databases: " + sth.fetch_all.join(", ")
       end
   end
他にコードブロックを取るtransactionメソッドがあります。 使い方は「トランザクションサポート」で説明されます。

サーバへの接続


以前、例に出したsimple.rbスクリプトはサーバへ接続するのに以下の ようにDBIのconnectメソッドを用いています。

   dbh = DBI.connect("dbi:Mysql:test:localhost", "testuser", "testpass")
connectの第一引数はデータソース名(DSN, data source name)で、 作成しようとする接続の種類を区別します。残りの2つの引数はMySQLアカウ ントのユーザ名とパスワードです。

DSN は以下の書式ならどれでも受け付けます。

   dbi:driver_name
   dbi:driver_name:db_name:host_name
   dbi:driver_name:key=val;key=val...
DSNは常にdbiもしくはDBIで始まります。(すべて大文字か すべて小文字かのどちらかです。両者の混在は受け付けません。) 続けて、ド ライバ名となります。MySQLの場合はドライバ名はMysqlです。正確 に先頭のみを大文字にして用いたほうが良いでしょう。(DBI仕様書にはドライ バ名は大文字小文字どちらでも良いと指示されてますが、最新の 0.0.18 でも それが常に真とはかぎりません。) 他のドライバを使用する場合は、適切なド ライバ名を使う必要があります。

dbi(もしくはDBI)とドライバ名は常にDSNに与える必要が あります。ドライバ名に続けて何も指定されてないときは、ドライバは(おそ らく)デフォルトのデータベースとホスト名を使って接続しようとします。 MySQLドライバの場合はデータベース名を指定する必要があるので、DBIを使っ たMySQLプログラミングでは第一の書式は使えません。他の書式を使ってくだ さい。第二の書式は2つの値を要求します。コロンで区切られたデータベース 名とホスト名です。第三の書式はセミコロンで区切られた param=valueの形式でパラメータの指定を行います。次のDSNはすべ て同じ意味をもちます。

   dbi:Mysql:test:localhost
   dbi:Mysql:host=localhost;database=test
   dbi:Mysql:database=test;host=localhost
param=valueの形式を使ったDSNの構文は最も柔軟です。というのも、 パラメータを任意の順番で指定できるからです。また、ドライバ固有のパラメー タを指定できる可能性もあります。ドライバは受け付けることのできる接続パ ラメータを拡張することができるからです。MySQLの場合は、hostdatabaseの他の追加のパラメータはportsocketflagです。(これらのパラメータは、 DBD::Mysqlの下にある Ruby MySQL モジュールの real_connectメソッドの対応するパラメータに渡されます。)

エラー処理とデバッグ

DBIメソッドが失敗するとDBIは例外を上げます。DBIメソッドはどんな例外で も上げる可能性はありますが、データベースに関する操作に対しては、それに 関係する例外クラス、DatabaseErrorがあります。このクラスの例外 オブジェクトにはerrerrstrstateという3 つの属性があります。DBIドキュメントはこれらの属性の意味を特定してはい ませんが、それぞれエラー番号、説明的なエラー文字列、そしてある種の「標 準」エラーコードをあらわしているように見えます。MySQLドライバは現時点 ではエラー文字列のみを提供しています。しかし、エラー番号を同様に戻すよ うにするドライバへパッチは簡単なことです。両方の値が利用可能と仮定する と、例外が起こったときにこれらの値を得るには次のようにします。

   rescue DBI::DatabaseError => e
       puts "An error occurred"
       puts "Error code: #{e.err}"
       puts "Error message: #{e.errstr}"
実行しようとするスクリプトが何をしているのかデバッグ情報を実行の順序ど おりに得るには、トレース可能な状態にしてください。そうするには、まず最 初にdbi/traceモジュールを読み込みます。
   require "dbi/trace"
dbi/tracedbiモジュールによって自動的には読み込まれ ません。というのも、AspectRモジュールのバージョン0.3.3以降に依存するか らです。AspectRはあなたのマシンに存在しないかもしれません。

dbi/traceモジュールはtraceメソッドを提供します。 traceメソッドでトレースのモードと出力先を設定をします。

   trace(mode, destination)
modeは 0(off)、1、 2、3 の値をとります。 destinationIOオブジェクトでないといけません。 デフォルト値はmodeは2で、destinationSTDERRです。

traceはクラスメソッドとして呼び出されると、続いて作成されるす べてのハンドルに対して影響します。または、ドライバ、データベースハンド ル、文ハンドルに対して個々にインスタンスメソッドとして呼び出すこともで きます。インスタンスメソッドとして呼ばれると、そのオブジェクトに由来す るすべてのオブジェクトに対してもトレースの設定が引き継がれます。例えば、 データベースハンドルに対してトレースを有効にすると、そこから作成された 文ハンドルのトレースの設定は同じになります。

トランザクション・サポート


DBIはトランザクションの抽象化を提供します。 しかし、抽象化が使えるかど うかは使用しているデータベースエンジンがトランザクションをサポートして いるかどうか、さらには使用するドライバがDBIレベルの抽象化を実装してい るかどうかに依存します。MySQLドライバの場合は、この抽象化は DBI 0.0.19 より前では機能していません。したがって、トランザクションを実行するには 明示的にSQL文を使って自動コミットレベル、コミット、ロールバックを制 御しないといけません。例えば以下のようにです。

   dbh.do("SET AUTOCOMMIT=0")
   dbh.do("BEGIN")
   ... statements that make up the transaction ...
   dbh.do("COMMIT")
DBI 0.0.19 以降では、MySQL でトランザクションの抽象化を利用できます。 抽象化の側面のひとつに、自動コミットのレベルをデータベースハンドルの AutoCommit属性の指定で設定できることにあります。
   dbh['AutoCommit'] = true
   dbh['AutoCommit'] = false
自動コミットが無効な間は(falseを設定)、トランザクションは2つ の方法で制御できます。次の例でその2つのアプローチを説明します。例とし てaccountテーブルを用い、資金をひとりの人から別の人にわたしま す。

ドライバ固有の機能を呼び出す。

DBIはデータベースに依存する特別な機能を利用するためのfunc メソッドを提供してます。例えば MySQL の C API には、使用中のコネクショ ンでの最新のAUTO_INCREMENTの値を戻すmysql_insert_id()関数があ ります。Ruby MySQL モジュールはデータベースハンドルのメソッドinsert_id を経由してこの関数を呼び出します。また、DBD::Mysql は DBI の funcメカニズムを経由してinsert_idにアクセスします。

funcの第一引数にはデータベース固有のメソッドの名前を指定しま す。残りの引数には必要ならばデータベース固有のメソッドが必要とする値を わたします。insert_idメソッドは追加の引数を必要とはしません。 したがってAUTO_INCREMENTの最新の値を得るには次のようにします。

   dbh.do("INSERT INTO people (name,height) VALUES('Mike',70.5)")
   id = dbh.func(:insert_id)
   puts "ID for new record is: " + id.to_s
DBD::Mysqlによりサポートされるその他のドライバ固有のメソッド は以下のとおりです。
   dbh.func(:createdb, db_name) 新しいデータベースを作成する。
   dbh.func(:dropdb, db_name)   データベースを削除する。
   dbh.func(:reload)            リロード操作を実行する。
   dbh.func(:shutdown)          サーバをシャットダウンする。
あなたの使用しているMySQLクライアントライブラリのバージョンが MySQL 4 以上の場合、createdbdropdbが使用できないことに注意 してください。これらのメソッドは MySQL 4 より Ruby MySQL モジュールで 使用してはいけない関数(deprecated functions)となっています。

ドライバ固有の機能を使用しなくても実現できることを実行するのに、ドライ バ固有の機能を使用したほうが利点がある場合があります。例えば、 SELECT LAST_INSERT_ID() を発行した結果は DBD::Mysqlinsert_id関数の戻り値でも得ることができ ます。両者ほほとんどの場合同じ結果を戻します。しかしinsert_id 関数のほうがより効率的です。というのもinsert_idは、問い合わせ を発行することなしにクライアント側に保持された値を戻すからです。 この効率上の利点は、あなたが関数の呼び出しにどれだけの注意を払うかに依 存します。insert_idの値はそれぞれの問い合せの実行毎にリセット されます。そのため、AUTO_INCREMENT値を生成する問い合わせを発 行した後、他の問い合わせを発行する前にアクセスしないといけません。対照 的にLAST_INSERT_ID()の値はサーバ側にもっと長い時間保持されま す。AUTO_INCREMENT値を生成する問い合わせが発行されない限りリ セットされることはありません。

その他の便利な機能

DBI::Utilsモジュールには興味深いメソッドがいくつかあります。

asciiメソッドとtableメソッドにはオプションの引数がい ろいろあります。オプションによって出力フォーマットや出力先を細かく制御 できます。オプションの情報を得るには、モジュールのソースコードを見てく ださい。

リソース


この記事の例で使用したスクリプトは以下の場所よりダウンロードできます。

   http://www.kitebird.com/articles/

ここには "Using the Ruby MySQL Module(英語)" という記事があり、 DBD::Mysql(DBD層のMySQLドライバ)の土台となっているRuby MySQLモジュール の説明をしてます。

Ruby DBI を使用するのに役立つ情報は以下の場所より見付けられます。