English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Ruby データベースアクセス DBI 教程

この章では、Rubyでデータベースにアクセスする方法について説明します。Ruby DBI モジュールは、Perl DBIモジュールに似たデータベースに依存しないインターフェースをRubyスクリプトに提供します。

DBI(Database independent interface)は、Rubyがデータベースに依存しないインターフェースを代表しており、Rubyコードとベースデータベース間に抽象レイヤーを提供します。データベースの切り替えを簡単に実現できるように、一連のメソッド、変数、規約を定義し、データベースに依存しない一貫したデータベースインターフェースを提供します。

DBI は以下と連携できます:

  • ADO (ActiveX Data Objects)

  • DB2

  • Frontbase

  • mSQL

  • MySQL

  • ODBC

  • Oracle

  • OCI8 (Oracle)

  • PostgreSQL

  • Proxy/Server

  • SQLite

  • SQLRelay

DBI アプリケーションアーキテクチャ

DBI は後で利用可能なすべてのデータベースに独立しています。Oracle、MySQL、Informixを使用している場合でも、DBIを使用できます。以下のアーキテクチャ図はこれを明確に示しています。

Ruby DBI の一般的なアーキテクチャは、2つのレベルを使用しています:

  • データベースインターフェース(DBI)レベル。このレベルはデータベースに依存しておらず、データベースサーバーのタイプに関係なく公共のアクセスメソッドを提供します。

  • データベースドライバ(DBD)レベル。このレベルはデータベースに依存しており、異なるドライバは異なるデータベースエンジンへのアクセスを提供します。MySQL、PostgreSQL、InterBase、Oracleなどはそれぞれ異なるドライバを使用します。各ドライバは DBI レベルからのリクエストを解釈し、それを特定のデータベースサーバーのリクエストにマッピングします。

インストール

MySQL データベースにアクセスする Ruby スクリプトを書く場合、まず Ruby MySQL モジュールをインストールする必要があります。

Mysql 開発パッケージのインストール

# Ubuntu
sudo apt-get install mysql-client
sudo apt-get install libmysqlclient15-dev
 
# Centos
yum install mysql-devel

Mac OS システムでは ~を修正する必要があります/.bash_profile または ~/.profile ファイルに以下のコードを追加してください:

MYSQL=/usr/local/mysql/bin
export PATH=$PATH:$MYSQL
export DYLD_LIBRARY_PATH=/usr/local/mysql/lib:$DYLD_LIBRARY_PATH

またはソフトリンクを使用:

sudo ln -s /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/lib/libmysqlclient.18.dylib

使用 RubyGems で DBI をインストール(推奨)

RubyGemsは約2003年11月、Rubyから 1.9版起成为Ruby標準ライブラリの一部。詳細については、以下を確認してください:Ruby RubyGems

使用 gem 安装 dbi 与 dbd-mysql:

sudo gem install dbi
sudo gem install mysql
sudo gem install dbd-mysql

ソースコードからインストール(Rubyバージョン 小于1.9この方法を使用して(この方法で使用)

このモジュールはDBDであり、以下から入手できます http://tmtm.org/downloads/mysql/ruby/ 上のダウンロード。

ダウンロード後の最新のパッケージを解凍し、ディレクトリに展開して以下のコマンドを実行してインストールします:

ruby extconf.rb
 
または
 
ruby extconf.rb --with-mysql-dir=/usr/local/mysql
 
または
 
ruby extconf.rb --with-mysql-config

次に、以下のコマンドを実行してコンパイルします:

make

Rubyおよびインストール/DBI

以下のリンクからRuby DBIモジュールをダウンロードしてインストールできます:

https://github.com/erikh/ruby-dbi

インストールを開始する前に、root権限を持っていることを確認してください。以下の手順でインストールを行います:

ステップ 1

git clone https://github.com/erikh/ruby-dbi.git

または直接zipパックをダウンロードして展開します。

ステップ 2

ディレクトリに移動 ruby-dbi-masterを使用して、ディレクトリ内で setup.rb スクリプトを実行して構成を行います。最も一般的な構成コマンドは、configパラメータの後にパラメータを指定しない場合です。このコマンドはデフォルトですべてのドライバーをインストールする設定です。

ruby setup.rb config

さらに具体的には、以下のように使用できます --withオプションを使用して、使用したい特定の部分をリストに挙げます。例えば、DBIのメインモジュールとMySQL DBDレイヤードライバーのみを構成する場合は、以下のコマンドを入力してください:

ruby setup.rb config --with=dbi,dbd_mysql

ステップ 3

最後に、以下のコマンドを使用してドライバーをインストールします:

ruby setup.rb setup
ruby setup.rb install

データベース接続

MySQLデータベースを使用している場合、データベースに接続する前に以下を確認してください:

  • あなたはTESTDBデータベースを作成しました。

  • あなたはTESTDBにEMPLOYEEテーブルを作成しました。

  • このテーブルには、FIRST_NAME、LAST_NAME、AGE、SEX、INCOMEというフィールドがあります。

  • ユーザーID「testuser」およびパスワード「test」を設定123「」でTESTDBにアクセス

  • RubyのモジュールDBIがあなたのマシンに正しくインストールされています。

  • MySQLのチュートリアルを確認し、MySQLの基本的な操作を理解しました。

以下はMySQLデータベース「TESTDB」に接続する例です:

オンラインサンプル

#!/usr/bin/ruby -w
 
require "dbi"
 
begin
     # 连接到 MySQL 服务器
     dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                       "testuser", "test123")
     # サーバーバージョン文字列を取得し、表示
     row = dbh.select_one("SELECT VERSION()")
     puts "Server version: " + row[0]
rescue DBI::DatabaseError => e
     puts "エラーが発生しました"
     puts "エラーコード: #{e.err}"
     puts "エラーメッセージ: #{e.errstr}"
ensure
     # サーバーとの接続を切断
     dbh.disconnect if dbh
end

このスクリプトを実行すると、Linuxマシン上に以下の結果が生成されます。

Server version: 5.0.45

データソースが接続に含まれている場合、データベースハンドル(Database Handle)が返され、 dbh 内に保存され、後で使用されるために残されます。さもなければ、 dbh NULL値に設定されます。e.err および e::errstr それぞれエラーコードとエラーストリングを返します。

最後に、このプログラムから退出する前に、データベース接続を閉じ、リソースを解放してください。

INSERT操作

データベーステーブルにレコードを作成したい場合、INSERT操作を使用する必要があります。

データベース接続が確立されると、それを使用する準備ができます。 do メソッドまたは prepare および execute メソッドを使用してテーブルを作成したり、データ表にデータを挿入したりします。

を使用して実行します。

行を返さない文は、 do データベース処理メソッドです。このメソッドは文字符串パラメータを持ち、その文が影響する行数を返します。

dbh.do("DROP TABLE IF EXISTS EMPLOYEE")
dbh.do("CREATE TABLE EMPLOYEE (
     FIRST_NAME CHAR(20) NOT NULL,
     LAST_NAME CHAR(20),
     AGE INT,  
     SEX CHAR(1),
     INCOME FLOAT )");

同様に、SQLを実行することもできます。 INSERT 文を使ってレコードをEMPLOYEEテーブルに挿入します。

オンラインサンプル

#!/usr/bin/ruby -w
 
require "dbi"
 
begin
     # 连接到 MySQL 服务器
     dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                       "testuser", "test123")
     dbh.do("INSERT INTO EMPLOYEE(FIRST_NAME",
                   LAST_NAME, 
                   AGE, 
         SEX, 
         INCOME)
          VALUES ('Mac', 'Mohan', 20, 'M', 2000)"
     puts "Record has been created"
     dbh.commit
rescue DBI::DatabaseError => e
     puts "エラーが発生しました"
     puts "エラーコード: #{e.err}"
     puts "エラーメッセージ: #{e.errstr}"
     dbh.rollback
ensure
     # サーバーとの接続を切断
     dbh.disconnect if dbh
end

を使用して呼び出します。 prepare および execute

DBIの prepare および execute メソッドを使用してRubyコード内でSQL文を実行します。

レコードを作成する手順は以下の通りです:

  • INSERT文を含むSQL文を準備します。これはステートメントを用いて行われます。 prepare 方法を使用して行います。

  • SQLクエリを実行し、データベースからすべての結果を選択します。これは以下を使用して行われます execute 方法を使用して行います。

  • 文のハンドルを解放します。これは、以下を使用して行われます。 finish APIを使用して完了します。

  • すべてが順調に進む場合、 commit この操作を行わない場合、または以下の方法で行うことができます。 rollback 取引を完了します。

以下はこれら二つの方法の文法です:

オンラインサンプル

sth = dbh.prepare(statement)
sth.execute
   ... 0または複数のSQL操作...
sth.finish

これらの二つの方法を使用してデータを伝達することができます。 bind 値をSQL文に与えます。時には入力値が事前に提供されていない場合があり、その場合にはバインド値を使用します。クエスチョンマーク(?)を使用して実際の値を置き換えます。実際の値は execute() APIを通じて渡されます。

以下の例では、EMPLOYEEテーブルに2つのレコードを作成しています:

オンラインサンプル

#!/usr/bin/ruby -w
 
require "dbi"
 
begin
     # 连接到 MySQL 服务器
     dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                       "testuser", "test123")
     sth = dbh.prepare("INSERT INTO EMPLOYEE(FIRST_NAME,"
                   LAST_NAME, 
                   AGE, 
         SEX, 
         INCOME)
                   VALUES (?, ?, ?, ?, ?)")
     sth.execute('John', 'Poul', 25, 'M', 2300)
     sth.execute('Zara', 'Ali', 17, 'F', 1000)
     sth.finish
     dbh.commit
     puts "Record has been created"
rescue DBI::DatabaseError => e
     puts "エラーが発生しました"
     puts "エラーコード: #{e.err}"
     puts "エラーメッセージ: #{e.errstr}"
     dbh.rollback
ensure
     # サーバーとの接続を切断
     dbh.disconnect if dbh
end

複数のINSERTを使用する場合、一度にクエリを準備し、ループ内で複数回実行することで、ループごとにdoを呼び出すよりも効率的です。

READ操作

データベースのREAD操作とは、データベースから有用な情報を取得することを指します。

データベース接続が確立されると、データベースをクエリする準備ができます。以下を使用できます do メソッドまたは prepare および execute メソッドを使用してデータベーステーブルから値を取得します。

レコードを取得する手順は以下の通りです:

  • 必要な条件に基づいてSQLクエリを準備します。これは以下を使用して行われます。 prepare 方法を使用して行います。

  • SQLクエリを実行し、データベースからすべての結果を選択します。これは以下を使用して行われます execute 方法を使用して行います。

  • 結果を順次取得し、これらの結果を出力します。これは以下を使用して行われます fetch 方法を使用して行います。

  • 文のハンドルを解放します。これは、以下を使用して行われます。 finish 方法を使用して行います。

以下の例では、EMPLOYEEテーブルからすべての給料(salary)が 1000のレコード。

オンラインサンプル

#!/usr/bin/ruby -w
 
require "dbi"
 
begin
     # 连接到 MySQL 服务器
     dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                       "testuser", "test123")
     sth = dbh.prepare("SELECT * FROM EMPLOYEE 
                        WHERE INCOME > ?")
     sth.execute(1000)
 
     sth.fetch do |row|
        printf "First Name: %s, Last Name : %s\n", row[0], row[1]
        printf "Age: %d, Sex : %s\n", row[2], row[3]
        printf "Salary :%d \n\n", row[4]
     end
     sth.finish
rescue DBI::DatabaseError => e
     puts "エラーが発生しました"
     puts "エラーコード: #{e.err}"
     puts "エラーメッセージ: #{e.errstr}"
ensure
     # サーバーとの接続を切断
     dbh.disconnect if dbh
end

これは以下の結果を生成します:

First Name: Mac, Last Name : Mohan
Age: 20, Sex : M
Salary :2000
First Name: John, Last Name : Poul
Age: 25, Sex : M
Salary :2300

データベースからレコードを取得する方法はまだたくさんあります。興味がある場合は、以下を参照してください Ruby DBI Read 操作

UPDATE操作

データベースのUPDATE操作とは、データベース内の1件または複数の既存のレコードを更新することを指します。以下の例では、SEXが'M'のすべてのレコードを更新します。ここでは、すべての男性のAGEを一歳増やします。これは3つのステップに分けられます:

  • 必要な条件に基づいてSQLクエリを準備します。これは以下を使用して行われます。 prepare 方法を使用して行います。

  • SQLクエリを実行し、データベースからすべての結果を選択します。これは以下を使用して行われます execute 方法を使用して行います。

  • 文のハンドルを解放します。これは、以下を使用して行われます。 finish 方法を使用して行います。

  • すべてが順調に進む場合、 commit この操作を行わない場合、または以下の方法で行うことができます。 rollback 取引を完了します。

オンラインサンプル

#!/usr/bin/ruby -w
 
require "dbi"
 
begin
     # 连接到 MySQL 服务器
     dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                       "testuser", "test123")
     sth = dbh.prepare("UPDATE EMPLOYEE SET AGE = AGE") + 1
                        WHERE SEX = ?")
     sth.execute('M')
     sth.finish
     dbh.commit
rescue DBI::DatabaseError => e
     puts "エラーが発生しました"
     puts "エラーコード: #{e.err}"
     puts "エラーメッセージ: #{e.errstr}"
     dbh.rollback
ensure
     # サーバーとの接続を切断
     dbh.disconnect if dbh
end

DELETE操作

データベースからレコードを削除する場合、DELETE操作を使用する必要があります。以下の例では、AGEが 20のすべてのレコード。この操作の手順は以下の通りです:

  • 必要な条件に基づいてSQLクエリを準備します。これは以下を使用して行われます。 prepare 方法を使用して行います。

  • SQLクエリを実行して、データベースから必要なレコードを削除します。これは以下を使用して行われます。 execute 方法を使用して行います。

  • 文のハンドルを解放します。これは、以下を使用して行われます。 finish 方法を使用して行います。

  • すべてが順調に進む場合、 commit この操作を行わない場合、または以下の方法で行うことができます。 rollback 取引を完了します。

オンラインサンプル

#!/usr/bin/ruby -w
 
require "dbi"
 
begin
     # 连接到 MySQL 服务器
     dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                       "testuser", "test123")
     sth = dbh.prepare("DELETE FROM EMPLOYEE 
                        WHERE AGE > ?")
     sth.execute(20)
     sth.finish
     dbh.commit
rescue DBI::DatabaseError => e
     puts "エラーが発生しました"
     puts "エラーコード: #{e.err}"
     puts "エラーメッセージ: #{e.errstr}"
     dbh.rollback
ensure
     # サーバーとの接続を切断
     dbh.disconnect if dbh
end

取引の実行

取引は取引の一致性を確保するメカニズムです。取引は以下の四つの属性を持たなければなりません:

  • 原子性(Atomicity):取引の原子性は、取引中に含まれるプログラムがデータベースの論理的な作業ユニットとして機能し、データに対する変更操作は全て実行されるか、全く実行されないことを意味します。

  • 一貫性(Consistency):取引の一致性は、取引を実行する前におよび実行後にデータベースが一貫性の状態にある必要があります。データベースの状態がすべての完全性制約を満たす場合、データベースは一貫しているとされます。

  • 隔離性(Isolation):取引の隔離性は、並行する取引が相互に隔離されていることを意味し、すなわち、一つの取引内の操作および操作中のデータは、他の変更を試みる取引から隔離されなければなりません。

  • 持続性(Durability):取引の持続性は、システムやメディアが故障した場合に、既にコミットされた取引の更新が失われないことを確実にする意味です。すなわち、一旦取引がコミットされると、データベース中のデータに対する変更は永続的で、どのデータベースシステムの故障にも耐えうるべきです。持続性はデータベースのバックアップとリカバリによって保証されます。

DBI は取引を実行するための二つの方法を提供しています。一つは、 commit または rollback 方法、取引をコミットまたはロールバックするために使用されます。他には、 transaction 方法、取引を実行するために使用できます。次に、これらの簡単な取引の実現方法について説明します:

方法 I

第一种方法使用 DBI の commit および rollback 方法を使用して明示的に取引をコミットまたはロールバックします:

オンラインサンプル

dbh['AutoCommit'] = false # 自動コミットを false に設定。
   begin
     dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 
             WHERE FIRST_NAME = 'John'")
     dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 
             WHERE FIRST_NAME = 'Zara'")
     dbh.commit
   rescue
     puts "transaction failed"
     dbh.rollback
   end
   dbh['AutoCommit'] = true

方法 II

第二种方法使用 transaction 方法。この方法は比較的簡単で、取引文を構成するコードブロックを持つ必要があります。transaction メソッド実行ブロック、ブロックが成功したかどうかによって、自動的に呼び出されます。 commit または rollback

オンラインサンプル

dbh['AutoCommit'] = false # 自动提交设置为 false
   dbh.transaction do |dbh|
     dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 
             WHERE FIRST_NAME = 'John'")
     dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 
             WHERE FIRST_NAME = 'Zara'")
   end
   dbh['AutoCommit'] = true

COMMIT操作

コミットは、データベースが変更を完了したことを示す操作であり、この操作以降、すべての変更は元に戻せません。

以下は、 commit メソッドの簡単な例。

dbh.commit

ROLLBACK操作を使用してください。

もし何かまたは何かの変更に不満があり、これらの変更を完全に元に戻したい場合は、 rollback メソッドの呼び出し例です。

以下は、 rollback メソッドの簡単な例。

dbh.rollback

データベース切断

データベース接続を切断するには、disconnect APIを使用してください。

dbh.disconnect

ユーザーがdisconnectメソッドを使用してデータベース接続を閉じた場合、DBIはすべての未完了のトランザクションをロールバックします。ただし、DBIの実装の詳細に依存することなく、アプリケーションは明示的にcommitやrollbackを呼び出すことができます。

エラー処理

多くの異なるエラーソースがあります。例えば、SQL文の構文エラー、接続失敗、キャンセルされたまたは完了したステートメントハンドルに対するfetchメソッドの呼び出しなどです。

DBIのメソッドが失敗すると、DBIは例外を投げます。DBIのメソッドはどんな種類の例外も投げることができますが、最も重要な2つの例外クラスは DBI::InterfaceError および DBI::DatabaseError

これらのクラスのExceptionオブジェクトには errerrstr および state 3つの属性があり、それぞれエラーコード、説明的なエラーストリング、標準のエラーコードを表しています。属性の詳細は以下の通りです:

  • err:発生したエラーの整数表示を返します。DBDがサポートしていない場合は、nilを返します。 nil。例えば、Oracle DBDは以下のように返します ORA-XXXX エラーメッセージの数字部分。

  • errstr:発生したエラーの文字列表現を返します。

  • state:発生したエラーのSQLSTATEコードを返します。SQLSTATEは5文字の長さの文字列です。多くのDBDはそれをサポートしていないため、nilを返します。

上の例で見た以下のコード:

rescue DBI::DatabaseError => e
     puts "エラーが発生しました"
     puts "エラーコード: #{e.err}"
     puts "エラーメッセージ: #{e.errstr}"
     dbh.rollback
ensure
     # サーバーとの接続を切断
     dbh.disconnect if dbh
end

スクリプトの実行中にスクリプトの実行内容に関するデバッグ情報を取得するには、トレースを有効にすることができます。これには、まずdbiをダウンロードする必要があります。/traceモジュールをインストールし、コントロールトラッキングモードと出力先の trace メソッド:

require "dbi/trace"
..............
 
trace(mode, destination)

modeの値は0(off)、1、2 または 3、destinationの値はIOオブジェクトであるべきです。デフォルト値は 2 およびSTDERR。

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

ハンドルを生成する方法がいくつかあります。これらの方法はコードブロックを通じて呼び出されます。コードブロックを持ち、それにメソッドを渡すコードブロックの利点は、コードブロックが終了するとハンドルが自動的にクリアされることです。以下の例がこの概念を理解するのに役立ちます。

  • DBI.connect :メソッドはデータベースハンドルを生成し、ブロックの終わりに呼び出すことを推奨します。 disconnect を使用してデータベースを切断します。

  • dbh.prepare :メソッドはステートメントハンドルを生成し、ブロックの終わりに呼び出すことを推奨します。 finish。ブロック内では、 execute メソッドを使用して文を実行します。

  • dbh.execute :このメソッドはdbh.prepareに似ていますが、dbh.executeはブロック内でexecuteメソッドを呼び出す必要はありません。ステートメントハンドルは自動的に実行されます。

例 1

DBI.connect コードブロックを持ち、それにデータベースハンドルを渡し、ブロックの終わりに自動的にハンドルが切断されます。

dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                  "testuser", "test123) do |dbh|

例 2

dbh.prepare コードブロックを持ち、それにステートメントハンドルを渡し、ブロックの終わりに自動的にfinishが呼び出されます。

dbh.prepare("SHOW 、DATABASES") do |sth|
       sth.execute
       puts "データベース: " + sth.fetch_all.join("、")
end

例 3

dbh.execute コードブロックを持ち、それにステートメントハンドルを渡し、ブロックの終わりに自動的にfinishが呼び出されます。

dbh.execute("SHOW 、DATABASES") do |sth|
   puts "データベース: " + sth.fetch_all.join("、")
end

DBI transaction メソッドもコードブロックを持つことができ、これは前の章で説明されています。

特定のドライバープログラムの関数と属性

DBIは、データベースドライバープログラムに追加の特定のデータベースの関数を提供し、これらの関数はユーザーがどんなHandleオブジェクトでも呼び出すことができます。 func メソッドを使用して呼び出します。

を使用して呼び出します。 []= または [] メソッドは特定のドライバの属性を設定または取得できます。

DBD::Mysql は以下の特定のドライバーの関数を実装しています:

番号関数および説明
1dbh.func(:createdb, db_name)
新しいデータベースを作成します。
2dbh.func(:dropdb, db_name)
データベースを削除します。
3dbh.func(:reload)
再読み込み操作を実行します。
4dbh.func(:shutdown)
サーバーを閉じます。
5dbh.func(:insert_id) => Fixnum
この接続の最も最近の AUTO_INCREMENT 値を返します。
6dbh.func(:client_info) => String
バージョンに応じて MySQL クライアント情報を返します。
7dbh.func(:client_version) => Fixnum
バージョンに応じてクライアント情報を返します。これは :client_info に似ていますが、文字列ではなく fixnum を返します。
8dbh.func(:host_info) => String
ホスト情報を返します。
9dbh.func(:proto_info) => Fixnum
通信に使用されるプロトコルを返します。
10dbh.func(:server_info) => String
バージョンに応じて MySQL サーバー側情報を返します。
11dbh.func(:stat) => Stringb>
データベースの現在の状態を返します。
12dbh.func(:thread_id) => Fixnum
現在のスレッドの ID を返します。

オンラインサンプル

#!/usr/bin/ruby
 
require "dbi"
begin
   # 连接到 MySQL 服务器
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", 
                       "testuser", "test123") 
   puts dbh.func(:client_info)
   puts dbh.func(:client_version)
   puts dbh.func(:host_info)
   puts dbh.func(:proto_info)
   puts dbh.func(:server_info)
   puts dbh.func(:thread_id)
   puts dbh.func(:stat)
rescue DBI::DatabaseError => e
   puts "エラーが発生しました"
   puts "エラーコード: #{e.err}"
   puts "エラーメッセージ: #{e.errstr}"
ensure
   dbh.disconnect if dbh
end

これは以下の結果を生成します:

5.0.45
50045
ローカルホスト via UNIX ソケット
10
5.0.45
150621
アップタイム: 384981  スレッド: 1  質問: 1101078  遅いクエリ: 4 \
オープン: 324  フラッシュテーブル: 1  オープンテーブル: 64  \
秒あたりクエリ平均: 2.860