この項では、SQL Anywhere DBI ドライバを使用する Ruby アプリケーションを作成する方法の概要を説明します。DBI モジュールの完全なドキュメントについては、オンラインで http://ruby-dbi.rubyforge.org/ を参照してください。
Ruby アプリケーションから DBI:SQLAnywhere インタフェースを使用するには、Ruby DBI モジュールを使用することを最初に Ruby に通知する必要があります。これを行うには、Ruby のソース・ファイルの先頭近くに次の行を挿入します。
require 'dbi' |
DBI モジュールは、必要に応じて SQL Anywhere データベース・ドライバ (DBD) インタフェースを自動的にロードします。
通常、データベースに対して 1 つの接続を開いてから、一連の SQL 文を実行して必要なすべての操作を実行します。接続を開くには、connect 関数を使用します。この戻り値は、接続時に後続の操作を行うために使用するデータベース接続のハンドルです。
connect 関数の呼び出しは、一般的に次の形式で行います。
dbh = DBI.connect('DBI:SQLAnywhere:server-name', user-id, password, options) |
server-name 接続先のデータベース・サーバ名です。"option1=value1;option2=value2;..." というフォーマットで接続文字列を指定することもできます。
user-id 有効なユーザ ID です。この文字列が空白でない場合、接続文字列に ";UID=value" が付加されます。
password ユーザ ID に対応するパスワードです。この文字列が空白でない場合、接続文字列に ";PWD=value" が付加されます。
options DatabaseName、DatabaseFile、ConnectionName などの追加接続パラメータのハッシュです。"option1=value1;option2=value2;..." というフォーマットで接続文字列に付加されます。
connect 関数を使用してみるには、データベース・サーバとサンプル・データベースを起動してからサンプルの Ruby スクリプトを実行します。
dbeng11 samples-dir\demo.db |
次のコード・サンプルは、SQL Anywhere サンプル・データベースへの接続を開いて閉じます。次の例では文字列 "demo" がサーバ名です。
require 'dbi' DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql') do |dbh| if dbh.ping print "Successfully Connected\n" dbh.disconnect() end end |
サーバ名の代わりに接続文字列を指定することもできます。たとえば、上記の場合、connect 関数の最初のパラメータを次のように置き換えることにより、スクリプトを変更できます。
require 'dbi' DBI.connect('DBI:SQLAnywhere:ENG=demo;DBN=demo;UID=DBA;PWD=sql') do |dbh| if dbh.ping print "Successfully Connected\n" dbh.disconnect() end end |
ユーザ ID とパスワードは接続文字列で指定されているので、connect 関数の 2 つ目と 3 つ目のパラメータは指定する必要はありません。ただし、追加接続パラメータのハッシュを渡す場合は、ユーザ ID とパスワードのパラメータに空の文字列
(''
) を指定します。
次の例は、追加接続パラメータをキーと値のペアのハッシュとして connect 関数に渡す方法を示しています。
require 'dbi' DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql', { :ConnectionName => "RubyDemo", :DatabaseFile => "demo.db", :DatabaseName => "demo" } ) do |dbh| if dbh.ping print "Successfully Connected\n" dbh.disconnect() end end |
開かれた接続へのハンドルを取得したら、データベースに格納されているデータにアクセスして修正できます。最も単純な操作は、おそらくいくつかのローを取得して出力することです。
SQL 文は最初に実行する必要があります。文から結果セットが返された場合、ステートメント・ハンドルを使用して、結果セットに関するメタ情報と、結果セットのローを取得できます。次の例では、メタデータからカラム名を取得し、フェッチされた各ローのカラム名と値を表示しています。
require 'dbi' def db_query( dbh, sql ) sth = dbh.execute(sql) print "# of Fields: #{sth.column_names.size}\n" sth.fetch do |row| print "\n" sth.column_info.each_with_index do |info, i| unless info["type_name"] == "LONG VARBINARY" print "#{info["name"]}=#{row[i]}\n" end end end sth.finish end begin dbh = DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql') db_query(dbh, "SELECT * FROM Products") rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" puts "Error SQLSTATE: #{e.state}" ensure dbh.disconnect if dbh end |
表示される出力の最初の数行を次に示します。
# of Fields: 8 ID=300 Name=Tee Shirt Description=Tank Top Size=Small Color=White Quantity=28 UnitPrice=9.00 ID=301 Name=Tee Shirt Description=V-neck Size=Medium Color=Orange Quantity=54 UnitPrice=14.00 |
終了したら、finish を呼び出してステートメント・ハンドルを解放することが重要です。finish を呼び出さなかった場合、次のようなエラーが表示される場合があります。
Resource governor for 'prepared statements' exceeded |
ハンドルのリークを検出するために、SQL Anywhere データベース・サーバでは、カーソルと準備文の数はデフォルトで接続ごとに最大 50 に制限されています。これらの制限を越えると、リソース・ガバナーによってエラーが自動的に生成されます。このエラーが発生したら、破棄されていない文のハンドルを確認してください。文のハンドルが破棄されていない場合は、prepare_cached を慎重に使用してください。
必要な場合、max_cursor_count と max_statement_count オプションを設定してこれらの制限を変更できます。max_cursor_count オプション [データベース]とmax_statement_count オプション [データベース]を参照してください。
ローを挿入するには、開かれた接続へのハンドルが必要です。ローを挿入する最も簡単な方法は、パラメータ化された INSERT 文を使用する方法です。この場合、疑問符が値のプレースホルダとして使用されます。この文は最初に準備されてから、新しいローごとに 1 回実行されます。新しいローの値は、execute メソッドのパラメータとして指定されます。
require 'dbi' def db_query( dbh, sql ) sth = dbh.execute(sql) print "# of Fields: #{sth.column_names.size}\n" sth.fetch do |row| print "\n" sth.column_info.each_with_index do |info, i| unless info["type_name"] == "LONG VARBINARY" print "#{info["name"]}=#{row[i]}\n" end end end sth.finish end def db_insert( dbh, rows ) sql = "INSERT INTO Customers (ID, GivenName, Surname, Street, City, State, Country, PostalCode, Phone, CompanyName) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" sth = dbh.prepare(sql); rows.each do |row| sth.execute(row[0],row[1],row[2],row[3],row[4], row[5],row[6],row[7],row[8],row[9]) end end begin dbh = DBI.connect('DBI:SQLAnywhere:demo', 'DBA', 'sql') rows = [ [801,'Alex','Alt','5 Blue Ave','New York','NY','USA', '10012','5185553434','BXM'], [802,'Zach','Zed','82 Fair St','New York','NY','USA', '10033','5185552234','Zap'] ] db_insert(dbh, rows) dbh.commit db_query(dbh, "SELECT * FROM Customers WHERE ID > 800") rescue DBI::DatabaseError => e puts "An error occurred" puts "Error code: #{e.err}" puts "Error message: #{e.errstr}" puts "Error SQLSTATE: #{e.state}" ensure dbh.disconnect if dbh end |
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |