Perl データベース接続

この章では、Perl のデータベース接続について説明します。

Perl 5 では、DBI モジュールを使用してデータベースに接続できます。

DBI の英語の正式名称は Database Independent Interface といい、中国語では「データベース独立接口(データベース独立インターフェース)」と呼ばれます。

DBI は Perl 言語におけるデータベースとの通信の標準インターフェースであり、一連のメソッド、変数、定数を定義し、特定のデータベースプラットフォームに依存しないデータベース永続層を提供します。


DBI 構造

DBI は特定のデータベースプラットフォームに依存しないため、Oracle、MySQL、Informix などのデータベースに適用できます。

図のように、DBI はすべての API(Application Programming Interface:アプリケーション・プログラミング・インターフェース)から送信された SQL データを取得し、対応するドライバに配布して実行し、最後にデータを取得して返します。

変数名の規約

以下に、比較的一般的な変数名の命名方法を示します。

$dsn    驱动程序对象的句柄
$dbh    一个数据库对象的句柄
$sth    一个语句或者一个查询对象的句柄
$h      通用的句柄 ($dbh, $sth, 或 $drh),依赖于上下文
$rc     操作代码返回的布什值(true 或 false)
$rv     操作代码返回的整数值
@ary    查询返回的一行值的数组(列表)
$rows   操作代码返回的行数值
$fh     文件句柄
undef   NULL 值表示未定义
\%attr  引用属性的哈希值并传到方法上

データベース接続

次に、MySQL データベースを例として、Perl がデータベースに対してどのように操作を行うかを示します。

ここでは、MySQL データベースに サンプル データベースを作成します。テーブルは Websites で、テーブル構造とデータは次の図のとおりです。

このテーブルをダウンロード:/static.jyshare.com/download/websites_perl.sql

次に、以下のコードを使用してデータベースに接続します。

例

#!/usr/bin/perl -w use strict; use DBI; my $host = "localhost"; # ホストアドレス my $driver = "mysql"; # インターフェースタイプ デフォルトは localhost my $database = "サンプル"; # データベース # ドライバオブジェクトのハンドル my $dsn = "DBI:$driver:database=$database:$host"; my $userid = "root"; # データベースユーザー名 my $password = "123456"; # データベースパスワード # データベースに接続 my $dbh = DBI->connect($dsn, $userid, $password ) or die $DBI::errstr; my $sth = $dbh->prepare("SELECT * FROM Websites"); # SQL 文をプリペアする $sth->execute(); # SQL 操作を実行 # コメント:この部分はバインド値操作を使用しています # $alexa = 20; # my $sth = $dbh->prepare("SELECT name, url # FROM Websites # WHERE alexa > ?"); # $sth->execute( $alexa ) or die $DBI::errstr; # ループですべてのデータを出力 while ( my @row = $sth->fetchrow_array() ) { print join('\t', @row)."\n"; } $sth->finish(); $dbh->disconnect();

挿入操作

実行手順:

  • prepare() API を使用して SQL 文をプリペアします。
  • execute() API を使用して SQL 文を実行します。
  • finish() API を使用してステートメントハンドルを解放します。
  • 最後に、すべてが正常に完了すれば、上記の実行操作をコミットします。
my $sth = $dbh->prepare("INSERT INTO Websites
                       (name, url, alexa, country )
                        values
                       ('Twitter', 'https://twitter.com/', 10, 'USA')");
$sth->execute() or die $DBI::errstr;
$sth->finish();
$dbh->commit or die $DBI::errstr;

アプリケーションは出力パラメータと入力パラメータをバインドすることもできます。次の例では、? プレースホルダの位置を変数で置き換えて、挿入クエリを実行します。

my $name = "Twitter";
my $url = "https://twitter.com/";
my $alexa = 10;
my $country = "USA";
my $sth = $dbh->prepare("INSERT INTO Websites
                       (name, url, alexa, country )
                        values
                       (?,?,?,?)");
$sth->execute($name,$url,$alexa, $country) 
          or die $DBI::errstr;
$sth->finish();
$dbh->commit or die $DBI::errstr;

更新操作

実行手順:

  • prepare() API を使用して SQL 文をプリペアします。
  • execute() API を使用して SQL 文を実行します。
  • finish() API を使用してステートメントハンドルを解放します。
  • 最後に、すべてが正常に完了すれば、上記の実行操作をコミットします。
my $sth = $dbh->prepare("UPDATE Websites
                        SET   alexa = alexa + 1 
                        WHERE country = 'CN'");
$sth->execute() or die $DBI::errstr;
print "更新的记录数 :" + $sth->rows;
$sth->finish();
$dbh->commit or die $DBI::errstr;

アプリケーションは出力パラメータと入力パラメータをバインドすることもできます。次の例では、? プレースホルダの位置を変数で置き換えて、更新クエリを実行します。

$name = 'サンプル';

my $sth = $dbh->prepare("UPDATE Websites
                        SET   alexa = alexa + 1 
                        WHERE name = ?");
$sth->execute('$name') or die $DBI::errstr;
print "更新的记录数 :" + $sth->rows;
$sth->finish();

もちろん、設定する値をバインドすることもできます。次のように、country が CN の alexa をすべて 1000 に変更します。

$country = 'CN';
$alexa = 1000:;
my $sth = $dbh->prepare("UPDATE Websites
                        SET   alexa = ?
                        WHERE country = ?");
$sth->execute( $alexa, '$country') or die $DBI::errstr;
print "更新的记录数 :" + $sth->rows;
$sth->finish();

データの削除

実行手順:

  • prepare() API を使用して SQL 文をプリペアします。
  • execute() API を使用して SQL 文を実行します。
  • finish() API を使用してステートメントハンドルを解放します。
  • 最後に、すべてが正常に完了すれば、上記の実行操作をコミットします。

次のコードは、Websites 内の alexa が 1000 より大きいデータをすべて削除します。

$alexa = 1000;
my $sth = $dbh->prepare("DELETE FROM Websites
                        WHERE alexa = ?");
$sth->execute( $alexa ) or die $DBI::errstr;
print "删除的记录数 :" + $sth->rows;
$sth->finish();
$dbh->commit or die $DBI::errstr;

do 文を使用する

dodo 文は UPDATE、INSERT、DELETE 操作を実行できます。使用法は簡潔で、実行が成功した場合は true を返し、失敗した場合は false を返します。例は次のとおりです。

$dbh->do('DELETE FROM Websites WHERE alexa>1000');

COMMIT 操作

commit はトランザクションをコミットし、データベースの操作を完了します:

$dbh->commit or die $dbh->errstr;

ROLLBACK 操作

SQL の実行中にエラーが発生した場合は、データをロールバックして、何も変更しないようにできます:

$dbh->rollback or die $dbh->errstr;

トランザクション

他の言語と同様に、Perl DBI のデータベース操作もトランザクション処理をサポートしています。その実装方法は 2 つあります:

1. データベース接続時にトランザクションを開始する

$dbh = DBI->connect($dsn, $userid, $password, {AutoCommit => 0}) or die $DBI::errstr;

上記のコードは、接続時に AutoCommit を false に設定しています。つまり、データベースに対して更新操作を行う場合、それらの更新は自動的にデータベースへ直接書き込まれず、プログラムが $dbh->commit を使用してデータを実際にデータベースへ書き込むか、$dbh->rollback を使用して直前の操作をロールバックする必要があります。

2. $dbh->begin_work() 文を使用してトランザクションを開始する

この方法では、データベース接続時に AutoCommit = 0 を設定する必要はありません。

1 回のデータベース接続で複数のトランザクション操作を実行でき、トランザクションの開始ごとにデータベースへ接続する必要はありません。

$rc  = $dbh->begin_work  or die $dbh->errstr;

#####################
##这里执行一些 SQL 操作
#####################

$dbh->commit;    # 成功后操作
-----------------------------
$dbh->rollback;  # 失败后回滚

データベース接続の切断

データベース接続を切断する必要がある場合は、disconnect API を使用できます:

$rc = $dbh->disconnect  or warn $dbh->errstr;
その他の拡張