by Hippo2000(1999/11/2)
DBD::CSVモジュールなのです。使ったことがないモジュールなのですが...。(未確認なだけ)
なおこのドキュメントではDBD::CSVモジュールを入れると入ってくるcsv.htmlを日本語化したものです。わかりにくい部分は本物を見てください。(^^;; 姉妹品のDBD::Fileもよろしく(^_^)
原本の著作権は Jochen Wiedmannさんがお持ちです。Jochen Wiedmannさんにはメールで了解をいただきました。
なお内容等が間違っていたら修正します。ご連絡ください
DBD::CSV - CSVファイルのためのDBIドライバ
use DBI;
$dbh = DBI->connect("DBI:CSV:f_dir=/home/joe/csvdb")
or die "Cannot connect: " . $DBI::errstr;
$sth = $dbh->prepare("CREATE TABLE a (id INTEGER, name CHAR(10))")
or die "Cannot prepare: " . $dbh->errstr();
$sth->execute() or die "Cannot execute: " . $sth->errstr();
$sth->finish();
$dbh->disconnect();
# MS Excelによってエキスポートされるように、「;」をセパレータとして
# CSVファイルを読み込みます。「;」をエスケープする必要があることに注意してください。
# そうでなければ、属性のセパレータとして扱われてしまいます。
$dbh = DBI->connect(qq{DBI:CSV:csv_sep_char=\\;});
$sth = $dbh->prepare("SELECT * FROM info");
# 同じ例。今度は「info.csv」をテーブルとして読み込みます:
$dbh = DBI->connect(qq{DBI:CSV:csv_sep_char=\\;});
$dbh->{'csv_tables'}->{'info'} = { 'file' => 'csv'};
$sth = $dbh->prepare("SELECT * FROM info");
これはα版のソフトウェアです:これは単にインターフェース(API)が最終化されていないためだけのために、「α版」になっています。コードの品質や安定性については「α版」というのは当てはまりません。
DBD::CSVモジュールはDBI(Perlのためのデータベース独立インタフェース)のためのドライバの1つです。これはSQL「エンジン」SQL::Statementと抽象DBIドライバDBD::Fileを基本とし、いわゆるCSVファイル(Comma separaed values=カンマ区切りファイル)へのアクセスを実装しています。そのようなファイルはMS AccessやMS Excelデータのエキスポートによく使われます。
詳細については、DBIの詳細については、DBI(3) 、SQL::Statementの詳細についてはSQL::Statement(3)、基本クラスDBD::Fileの詳細についてはDBD::File(3) をご覧ください。
DBD::Fileが使っているシステム依存の機能はflock()関数だけです。そのため(理論的には)このモジュールはflock()が動くすべてのシステム、特に全てのUnixマシーンとWindows NTで機能するはずです。Windows95とMacOSではflock()は使えませんが、このモジュールを使うことができます。
他のDBIドライバとは違って、外部のSQLエンジンや稼動しているサーバが必要ありません。必要なのは以下のPerlモジュールだけです。これらはCPANミラーから利用することができます。例えば:
ftp://ftp.funet.fi/pub/languages/perl/CPAN/modules/by-module
このモジュール(そして上記の準備するもの)のインストールはとっても簡単です。以下のようにアーカイブから解凍して、取り出します。
gzip -cd DBD-CSV-0.1000.tar.gz | tar xf -
(これはUnixユーザ用です。WindowsユーザはWinZipまたは同類のものを参照してください)
そして以下のように入力します:
cd DBD-CSV-0.1000
perl Makefile.PL
make
make test
テストが失敗したら、私に教えてください。そうでなければ次に進みます。
make install
rootまたは管理者の権限が必要であることに注意してください。もしそれをもっていなければ、あなた自身のディレクトリへのインストール方法の詳細についてExtUtils::MakeMakerをご覧ください。
訳者注:
ActivePerlではPPMを使ってください。もっと簡単にインストールすることができます。
データベースハンドルの作成は通常、データベースサーバへの接続を意味します。
use DBI;
my $dbh = DBI->connect("DBI:CSV:f_dir=$dir");
上記のコマンドはドライバが示すテーブル(別名ファイル)を作成あるいはオープンするディレクトリはを読み込みます。デフォルトは現在のディレクトリです。これは以下のものと同じです。
$dbh = DBI->connect("DBI:CSV:");
$dbh = DBI->connect("DBI:CSV:f_dir=.");
DSN文字列にセミコロンで区切って、他の属性を設定することもできます。
以下のようなコマンドを使って、テーブルを作成したり、削除することができます:
$dbh->do("CREATE TABLE $table (id INTEGER, name CHAR(64))");
$dbh->do("DROP TABLE $table");
現在、カラム名は格納されますが、他のデータは格納されないことに気をつけてください。そのためカラムのデータ型(例えばINTEGERやCHAR(x))、カラムの属性(NOT NULL、PRIMARY KEY、...)といった他の情報は黙って無視されます。今後のリリースで、これは変更されるかもしれません。
削除は何の警告もなくファイルを削除します。
詳細についてはDBI(3) をご覧ください。
テーブル名はSQLの文法の制約から、勝手に付けることは出来ません。テーブル名に適切なSQL識別子をつけることをお勧めします。最初の文字は英字、2文字目以降は任意の英数字とします。他のファイルを使いたい場合には、ファイル名を'/'、'./'、'../'から始めなければなりません、そして空白が入ってはいけません。
以下の例では、テーブルにあるデータを挿入し、取り出します:
まずデータを挿入します:
$dbh->do("INSERT INTO $table VALUES (1, "
. $dbh->quote("foobar") . ")");
'foobar'という単語をエスケープするためにquoteメソッドを使っていることに注意してください。例えバイナリデータが入っていなくても、すべての文字列はエスケープするべきです。
次の例ではパラメータを使っています:
$dbh->do("INSERT INTO $table VALUES (?, ?)", undef,
2, "It's a string!");
ここでは、自動的におこなわれるのでquoteメソッドを使う必要がないことに注意してください。このやり方は特に繰り返しに適した設計となっています。パフォーマンスが問題となる場合には、この方法を使うことをお勧めします。
undefについて疑問に思うかもしれません。ご心配なく、それはそのまま扱われます。(^^;; それは私はこれまで使ったことがない属性引数で、prepareメソッドへの2番目の引数として解析されます。
データを取り出すためには、以下のようにします:
my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id";
my($sth) = $dbh->prepare($query);
$sth->execute();
while (my $row = $sth->fetchrow_hashref) {
print("Found result row: id = ", $row->{'id'},
", name = ", $row->{'name'});
}
$sth->finish();
また、カラムバインディングを使って同じ例をすると:
my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id";
my($sth) = $dbh->prepare($query);
$sth->execute();
my($id, $name);
$sth->bind_columns(undef, \$id, \$name);
while ($sth->fetch) {
print("Found result row: id = $id, name = $name\n");
}
$sth->finish();
もちろん、入力パラメータを使うこともできます。3番目の例を以下に示します:
my($query) = "SELECT * FROM $table WHERE id = ?";
my($sth) = $dbh->prepare($query);
$sth->bind_columns(undef, \$id, \$name);
for (my($i) = 1; $i <= 2; $i++) {
$sth->execute($id);
if ($sth->fetch) {
print("Found result row: id = $id, name = $name\n");
}
$sth->finish();
}
これらのメソッドの詳細は DBI(3) をご覧ください。WHERE節の詳細についてはSQL::Statement(3) をご覧ください。
データ行はUPDATEステートメントで変更されます:
$dbh->do("UPDATE $table SET id = 3 WHERE id = 1");
さらに行を削除するためにはDELETEステートメントを使います:
$dbh->do("DELETE FROM $table WHERE id > 1");
上記の例では、戻り値について一切気にしてきませんでした。これはお勧めできません。そうではなく以下のように書くべきでした(例えば):
my($query) = "SELECT * FROM $table WHERE id = ?";
my($sth) = $dbh->prepare($query)
or die "prepare: " . $dbh->errstr();
$sth->bind_columns(undef, \$id, \$name)
or die "bind_columns: " . $dbh->errstr();
for (my($i) = 1; $i <= 2; $i++) {
$sth->execute($id)
or die "execute: " . $dbh->errstr();
if ($sth->fetch) {
print("Found result row: id = $id, name = $name\n");
}
}
$sth->finish($id)
or die "finish: " . $dbh->errstr();
これは明らかに冗長です。幸いにも私達にはDBIのRaiseError属性があります:
$dbh->{'RaiseError'} = 1;
$@ = '';
eval {
my($query) = "SELECT * FROM $table WHERE id = ?";
my($sth) = $dbh->prepare($query);
$sth->bind_columns(undef, \$id, \$name);
for (my($i) = 1; $i <= 2; $i++) {
$sth->execute($id);
if ($sth->fetch) {
print("Found result row: id = $id, name = $name\n");
}
}
$sth->finish($id);
};
if ($@) { die "SQL database error: $@"; }
これは短いだけでなく、サブルーチンのなかでDBIメソッドを使ったときにさえ機能します。
これらの属性はDBD::FileではなくDBIそのもので扱われます、そのためこれらは期待する通りの動きをします。
Active
ActiveKids
CachedKids
CompatMode (未使用)
InactiveDestroy
Kids
PrintError
RaiseError
Warn (未使用)
以下のDBI属性はDBD::Fileによって扱われます:
$sth->execute以降、適正です$sth->prepare以降、適正です$sth->execute以降、適正です;Selectステートメント以外ではundefです。以下の属性、メソッドはサポートされていません:
bind_param_inout
CursorName
LongReadLen
LongTruncOk
追加のDBI属性として、以下のdbh属性を使うことができます:
これらの属性はデフォルトのText::CSV_XSによってcsv_classのインスタンスを生成するときに使用されます。代わりにインスタンスをcsv_csvとして渡すことができます。後から渡されたものが優先されます。その場合、binary属性がtrueに設定されなければならないことに注意してください。
加えて、csv_tables属性でテーブル毎にこれらの属性を置きかえることもできます。
"$dbh->{f_dir}/$table"
空の配列リファレンスを指定すると、ドライバは最初の行を読み、カラムの数を数えて、カラム名をcol0、col1...のように生成します。
例: /etc/passwd をCSVファイルとして使いたいとします。(^_^) 一番簡単な方法は...:
require DBI;
my $dbh = DBI->connect("DBI:CSV:f_dir=/etc;csv_eol=\n;"
. "csv_sep_char=:;csv_quote_char=;"
. "csv_escape_char=");
$dbh->{'csv_tables'}->{'passwd'} = {
'col_names' => ["login", "password", "uid", "gid", "realname",
"directory", "shell"]
};
$sth = $dbh->prepare("SELECT * FROM passwd");
他の方法として、すべての属性をデフォルトのままとして、テーブル毎にそれらを書きかえます:
require DBI;
my $dbh = DBI->connect("DBI:CSV:");
$dbh->{'csv_tables'}->{'passwd'} = {
'eol' => "\n",
'sep_char' => ":",
'quote_char' => undef,
'escape_char' => undef,
'file' => '/etc/passwd',
'col_names' => ["login", "password", "uid", "gid", "realname",
"directory", "shell"]
};
$sth = $dbh->prepare("SELECT * FROM passwd");
これらのメソッドはDBD::Fileから継承されています:
もし他のディレクトリのサブディレクトリを読みたければ、以下のようにしてください:
my($drh) = DBI->install_driver("CSV");
my(@list) = $drh->data_sources('f_dir' => '/usr/local/csv_data' );
my($dbh) = DBI->connect("DBI:CSV:f_dir=/usr/local/csv_data");
my(@list) = $dbh->func('list_tables');
SQLの観点からはテーブル名として適切でないものも含めて、ディレクトリに入っている全てのファイルがリストに含まれることに注意してください。上記の「テーブルの作成、削除」のご覧ください。
データを挿入あるいは取り出すさいに、驚くことがあるかも知れません:DBD::CSVは、データ型を、特にNULLを正しく扱えません。それは、もし整数値を入れようとするとき起きるかもしれません。取り出すと文字を返すのです。もちろん文字列には数字が入っているので、多分、本当の問題にはならないでしょう。しかし以下のものは動きません:
$dbh->do("INSERT INTO $table (id, name) VALUES (?, ?)",
undef, "foo bar");
$sth = $dbh->prepare("SELECT * FROM $table WHERE id IS NULL");
$sth->execute();
my($id, $name);
$sth->bind_columns(undef, \$id, \$name);
while ($sth->fetch) {
printf("Found result row: id = %s, name = %s\n",
defined($id) ? $id : "NULL",
defined($name) ? $name : "NULL");
}
$sth->finish();
今入れた行は絶対に返ってきません。CSVファイルを調べれば、理由は明らかです。対応する行は以下のようになります:
"","foo bar"
いいかえれば、NULLは格納されず、空文字が格納されます。CSVファイルはNULL値という概念を持っていません。nameにもNULL値を入れると、驚くべきことに上記の例は動きます。CSVファイルを調べると、またその答えがわかるでしょう:
""
いいかえれば、DBD::CSVはNULL値をカラムを減らした行を出力することによって「エミュレート」しているのです。もちろん、これは一番右のカラムがNULL、次のカラムもNULL、...、でも一番左のカラムは絶対にNULLでない場合にのみ機能します。
テーブル名の制限については、上記 テーブルの作成と削除をご覧ください。
DBD::CSVの拡張
単なるDBD::FileまたはSQL::Statementモジュールの制限:
flock()
を使っています。しかしこの関数はプラトホームによっては使えない場合があります。flock()
はMacOSとWindows95では使えません:ロックがまったくありません(多分、常にシングル・ユーザなので、これらのオペレーティング・システムではあまり重要ではないでしょう。)。(原文のまま)
This module is Copyright (C) 1998 by
Jochen Wiedmann
Am Eisteich 9
72555 Metzingen
Germany
Email: joe@ispsoft.de
Phone: +49 7123 14887
All rights reserved.
You may distribute this module under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.
DBI(3), Text::CSV_XS(3), SQL::Statement(3)
DBD::CSVの使い方のヘルプについては、DBIユーザメーリングリストをご覧ください:
http://www.isc.org/dbi-lists.html
DBIの一般的な情報については以下のサイトをご覧ください:
http://www.symbolstone.org/technology/perl/DBI
ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。