特3-4 PGI 03.7.26 17:15 ページ104

第4章

プログラムから MySQL 操作
Java，Perl，PHP からの利用方法
Shibuya Perl Mongers 小山 浩之◎ OYAMA Hiroyuki ● oyama@cpan.org
ステムで，データを管理するサーバと，それを利用すはじめにるクライアントが協調して動作します．通常MySQLを利用する場合は，クライアント側のプログラムを記

本章では，Java，Perl，PHP からMySQL を操作す述することになります．

るプログラミングインタフェースを解説します．使用

表1 は，クライアントライブラリ各言語に用意されするメソッドや属性の名前はプログラミング言語とイているプログラミングインタフェースの概要です．Java

ンタフェースごとに異なりますが，RDBMS を利用す用に提供されているConnector/Jを除き，PerlのDBI，るプログラムは，PHP のDB や他の多くの実装ではMySQL のネイティブライブラリであるlibmysqlclientをラッピングして使¡接続／切断用する構成をとっています注1．

¡エラー処理Connector/J のセットアップ¡クエリ送信¡レスポンス受信

Java用の実装の1 つであるMySQL Connector/Jは，の4 つの要素を把握していれば記述することができま

MySQL の開発元であるMySQL ABによってメンテナ

す．本章は各言語に用意されているプログラミングイ

ンスされているJDBC 3.0準拠のドライバです．現在安ンタフェースを，これら4 つの要素ごとに比較しなが定版のバージョン3.0系と開発版の3.1系が配付されてら解説します．

おり，安定版の最新バージョンは3.0.8です注2．
Connector/J の前身であるMM.MySQL ドライバとクライアントライブラリ同様にソースコードが公開されており，ライセンスは
GNU General Public Licenseか，商用ライセンスのいMySQLはクライアント／サーバ型のデータベースシずれかを選択できます．

▼表 1 API の概要
言語

API

実装

通信の特徴

Java

JDBC

MySQL Connector/J

通信プロトコルを独自実装

Perl

DBI

DBD::mysql

通信は libmysqlclient を使用

PHPDBDB̲mysql

通信は libmysqlclient を使用

注 1）現在はメンテナンスされていませんが，Java と同様に Perl だけで記述されたライブラリ Net::MySQL と DBD::mysqlPP という選択肢もあります．これらのライブラリは基本的に Perl と Socket が利用できる，あらゆる環境から MySQL を操作できます．
注 2）http://www.mysql.com/products/connector-j/

104● WEB +DB PRESS Vol.16

特3-4 PGI 03.7.26 17:15 ページ105

プログラムから MySQL 操作
Java，Perl，PHPからの利用方法 第 4 章
Connector/Jをセットアップするには，http://www.

DB̲mysql のセットアップ

mysql.com/downloads/api-jdbc-stable.html からをダウンロード・展

PHP 用の実装であるDB̲mysql は，PEAR のDB パ開し，パッケージに含まれるmysql-connector-java-ッケージに含まれており，Stig Bakken 氏によってメ

3.0.8-stable-bin.jar へのパスをCLASSPATH に追加すンテナンスされています注4．Perl のDBD::mysql と同るか，$JAVA̲HOME/jre/lib/ext ディレクトリに設様にlibmysqlclient ライブラリを使用するので，PHP置するだけです（図1）．のセットアップの前にlibmysqlclientライブラリと，そSource and Binaries (tar.gz)

DBD::mysql のセットアップのヘッダファイルがインストールされている必要があります注5．

Perl 用の実装の1 つであるDBD::mysql は，Jochen

PHP4 系列の場合は，libmysqlclient ライブラリがWiedmann氏によってメンテナンスされているDBI用

インストールされた状態で，PHP のconfigure スクリのドライバです．現在バージョン2.9002が配付されてプトに--with-mysql オプションを指定し，PHP をビルおり，ライセンスはPerlと同じくGNU General Public

ドすればDB̲mysql が利用できるようになります（図LicenseかArtistic Licenseのいずれかを選択できます注3．

4）．

DBD::mysqlをセットアップする前に，まずlibmysql

現在開発中のPHP5系列の場合は，ライセンスの相client ライブラリと，そのヘッダファイルがインスト違の問題でMySQL のクライアントライブラリはバンールされている必要があります．

ドルされていません．これについては第1 章を参照しパッケージマネージャにRPM を使用している場合てください．
◇ ◇ ◇は，MySQL-develパッケージで必要なファイルをインストールできます．http://www.mysql.com/downloads

各プログラミングインタフェースのセットアップの/mysql-4.0.html から，使用しているアーキテクチャ

詳細については，各パッケージのドキュメントを参照に対応したパッケージをダウンロードし，インストーしてください．

ルしてください（図2）．
www.mysql.com では，RPM 以外にも Solaris，接続／切断

FreeBSD，Mac OS X など一般的なプラットフォーム向けのバイナリパッケージとソースパッケージを配付

MySQL サーバへ接続し切断する手続きは，いずれしていますので，インストールする環境に合わせて選
図 2 ● MySQL-devel パッケージのインストール択してください．

% sudo rpm -i MySQL-devel-4.0.14-0.i386.rpm

次にDBI とDBD::mysql モジュールをインストールします．これらはCPANモジュールを使用して，ネットワークインストールができます（図3）．

図 3 ● DBD::mysql のインストール% sudo perl -MCPAN -e 'install "DBD::mysql"'

図 4 ● DB̲mysql のセットアップ% cd php-4.3.2/% ./configure --with-mysql% make% sudo make install

図 1 ● Connector/J のセットアップ% tar zxvf mysql-connector-java-3.0.8-stable.tar.gz% cd mysql-connector-java-3.0.8-stable/% cp mysql-connector-java-3.0.8-stable-bin.jar $JAVA_HOME/jre/lib/ext/

注 3）http://search.cpan.org/author/RUDY/DBD-mysql/
注 4）http://pear.php.net/package-info.php?package=DB
注 5）libmysqlclient ライブラリのセットアップは，前項「DBD::mysql のセットアップ」の説明を参照してください．

WEB +DB PRESS Vol.16 ●105

特3-4 PGI 03.7.26 17:15 ページ106＃3のプログラミングインタフェースも同じような手続き

表3 で示した例の他にも指定可能なパラメータが存をふみます．各言語で接続し切断するだけのプログラ

在しますので，詳しくは各ドライバのマニュアルを参

ムは，リスト1 〜3 のようになります．

照してください．

いずれのプログラミングインタフェースも接続する

エラー処理

データベースの種類と場所，さらに細かなパラメータを文字列DSN（Data Source Name）で指定します．
各インタフェースの接続用メソッドの引数を表 2 に，エラー処理はプログラミングインタフェースの差異

使用するDSN の例を表3 にまとめます．

よりも，プログラミング言語の差異が顕著に表れます．大きく分類すると例外処理をサポートする言語▼リスト 1 Java での接続／切断と，サポートしない言語に分類することができます

import java.sql.*;（表4）．
public class ConnectDemo {public static void main(String argv[]) {try {Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/dbname","user", "password");conn.close();}catch (SQLException e) {/* エラー処理 */e.printStackTrace();}catch (ClassNotFoundException e) {/* エラー処理 */e.printStackTrace();}}}

JavaやPerlのように例外処理をサポートする言語では，ブロック単位にエラー処理を記述するスタイルをとるので簡潔なコードになりますが，PHPのように例外処理をサポートしない言語では，各処理単位でその都度エラー処理を記述する必要があります．なおPHPのDB クラス（と親のPEAR クラス）は，エラー時にコールバックされる関数を設定できますので，表4 のように例外処理的な記述は可能です．

▼リスト 2 Perl での接続／切断#!/usr/bin/perluse DBI;use strict;eval {
my $conn = DBI->connect('dbi:mysql:hostname=localhost;database=dbname','user', 'password',{ RaiseError => 1, PrintError => 0 });$conn->disconnect();};
if ($@) {# エラー処理
warn $DBI::errstr;}__END__▼リスト 3 PHP での接続／切断▼表 2 接続メソッドの引数
言語

接続メソッドの引数

Java

java.sql.DriverManager.getConnection(String DSN, String USER, String PASSWD);

Perl

DBI->connect($DSN, $USER, $PASSWD, \%OPTIONS);

PHP

DB::connect($DSN, $OPTIONS);▼表 3 DSN の差異
言語

DSN の書式

Java"jdbc:mysql:///dbname""jdbc:mysql://hostname:port/dbname"Perl'dbi:mysql:dbname''dbi:mysql:dbname@hostname:port''dbi:mysql:database=dbname;host=hostname;port=port'

PHP'mysql:///dbname''mysql://hostname:port/dbname''mysql://username:password@hostname:port/dbname'<?php
require_once 'DB.php';$conn = DB::connect('mysql://user:password@localhost/dbname');if (DB::isError($conn)) {/* エラー処理 */die($conn->getMessage());}$conn->disconnect();?>

106● WEB +DB PRESS Vol.16▼表 4 エラーハンドリングの作法
言語

例外処理 例

Java○try { code; } catch (Exception) { error_code; }Perl○eval { code; }; if ($@) { error_code; }PHP△code; if (DB::isError($obj)) { error_code; }特3-4 PGI 03.7.26 17:15 ページ107

プログラムから MySQL 操作
Java，Perl，PHPからの利用方法 第 4 章
ルダを使用します．SQL 文に ?

クエリ送信でマーキングした場所をプレースホルダと呼びます．プレースホルダを使用するSQL 文はprepare 系のメソッドでステートメRDBMS へ送信するクエリには，UPDATE 文やントを生成し，実行前（もしくは実行時）に設定したINSERT 文などの更新系 SQL，SELECT 文などの参値でSQL文中のプレースホルダを置き換え，クエリを照系SQL の2 種類があります．更新系SQL の場合は実行します（図5）．プレースホルダに値を埋め込む際クエリの送信後，影響を受けたレコード数などのチェにエスケープ処理などが自動的に行われますので，SQLックを行います．参照系SQL の場合はクエリの送信的に不正な文字を埋め込む場合でも，適切にエスケー後，検索結果のレコードセットを受信します．

図 5 ●プレースホルダとバインド値

更新系 SQL"SELECT * FROM user WHERE name = ? AND age = ? "UPDATE 文やINSERT 文などの更新系SQL を実行した後は，クエリが成功したか否か，また影響を受け"myname"たレコード数はいくつあったかを調べます．
表 5 は更新系SQL を実行する手続きの例です．各18▼表 5 更新系 SQL の実行

プログラミングインタフェース共に，SQL をもとに， 言語 手続き
SQLとSQLの状態を抽象化したステートメントハンド Java PreparedStatement query = conn.prepareStatement(SQL);
int result = query.executeUpdate();query.close();

ルを生成し，そのハンドルを通じてSQL を実行します．いずれの言語のメソッドも戻り値として，実行しPerl

my $query = $conn->prepare($SQL);
my $result = $query->execute(@params);

PHP$query = $conn->prepare($SQL);$result = $conn->execute($query, $params_array);

たSQL によって影響を受けたレコード数を返します．

参照系 SQLSELECT 文などの参照系SQL を実行した後は，検索結果のレコードセットを受信します．

▼表 6 参照系 SQL の実行
言語

手続き

Java

PreparedStatement query = conn.prepareStatement(SQL);
ResultSet result = query.executeQuery();
while (result.next()) {String row0 = result.getString(1);String row1 = result.getString(2);String row2 = result.getString(3);}result.close();query.close();Perl

my $query = $conn->prepare($SQL);
my $result = $query->execute(@params);
while (my $row = $query->fetch()) {$row->[0];$row->[1];$row->[2];}$query->finish();PHP$query = $conn->prepare($SQL);$result = $conn->execute($query, $params_array);while ($row = $result->fetchRow()) {$row[0];$row[1];$row[2];}$result->free();

表6 は各インタフェースで参照系SQLを実行する例
です．メソッド名や手続きは似通っていますが，JavaとPHPはステートメントハンドルから生成した，レコードセットオブジェクトから値を参照しているのに対し，Perl のDBI はレコードセットオブジェクトを生成せずに，ステートメントハンドルから値を参照している点が微妙ながら大きく異なるポイントです．
またPerlとPHPは直接レコードの値を参照できますが，Javaの場合は受け取りたいデータ型に応じたアクセッサメソッドで値を取り出す必要があります．例で挙げたgetString( )メソッドの他に，getInt( )，getDate( )，getObject( )などのデータ型に応じたメソッドが用意されています．

プレースホルダ
送信するSQLを動的に組み立てる場合はプレースホ

WEB +DB PRESS Vol.16 ●107

特3-4 PGI 03.7.26 17:15 ページ108＃3

プされます．プレースホルダの処理は，各プログラミ適切にエスケープしていない場合，悪意を持ったユーングインタフェースのドライバによって実装されます．

ザに不正なSQL の実行を許してしまうSQL Injection

表7 のように，各プログラミングインタフェース共と呼ばれる問題が発生します．このセキュリティ面でに，プレースホルダは ? でマーキングします．値のの問題を簡単かつ確実に回避できますので，動的に設定方法はそれぞれ異なり，Java はsetString( )やSQL文を組み立てる場合は特別な理由がない限りプレsetInt( )メソッドでIndexを指定して値を設定し，Perlースホルダを使用してください．とPHPはexecute( )メソッドの引数に配列で値を設定します．

まとめ

外部からの入力値をSQL に埋め込む際に入力値をJava のJDBC，Perl のDBI，PHP のDB の各ライブ▼表 7 プレースホルダと値のバインド
言語

手続き

Java

PreparedStatement query = conn.prepareStatement("SELECT * FROM user WHERE name = ? AND age = ?");
query.setString(1, "myname");query.setInt(2, 18);ResultSet result = query.executeQuery();

PerlPHP

ラリによる，MySQL へのプログラミングインタフェースの利用方法とそれらの差異を見てきました．どのインタフェースも同じような思想のもとで設計されているためにとてもよく似た API になっています．
RDBMS のクライアントを実装する場合，プログラミ

my $query = $conn->prepare('SELECT * FROM user WHERE name = ? AND age = ?');
my $result = $query->execute('myname', 18);

ング上の手続きは言語や環境を問わずどれも同じなの$query = $conn->prepare('SELECT * FROM user WHERE name = ? AND age = ?');
$result = $conn->execute($query, array('myname', 18));

ることができるはずです．#

108● WEB +DB PRESS Vol.16

で，使用するメソッドやオブジェクトの差異にさえ注意すれば，言語や環境が変わっても同じように開発す