DBD::AnyDataモジュール Ver. 0.05 (日本語チョウ訳)

by Hippo2000(2001/8/5,2002/5/22)

日本語チョウ訳シリーズ DBD::AnyDataモジュールなのです。
ドキュメントとしてはかなり「粗い」です。間違ってそうなことはあるし、書いてないことも多いし。
でもこれは大きな変革になるかもしれません。AnyData、SQL::Squishも合わせて注目です。

いつものことですが、わかりにくい(あやしい)説明は本物を見てください。(^^;

原本の著作権はJeff Zucker氏がお持ちです(詳しくは著作権情報を見てください)。Jeff Zucker氏にはメールで了解をいただきました。

内容等が間違っていたら修正します。ご連絡ください。

変更履歴:

2002/5/22 :桜本さんからの指摘をうけて{ key1=>,val1 ... },の間違いを修正


目次


名前

 DBD::AnyData -- XML、CSVそしてその他のフォーマットへのDBIアクセス


概要

 use DBI;
 my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
 $dbh->func( 'trains', 'CSV', '/users/joe/cars.csv', 'ad_catalog');
 $dbh->func( 'bikes',  'XML', [$xml_str],            'ad_import');
 $dbh->func( 'cars',   'DBI', $mysql_dbh,            'ad_import');
 #
 # ... テーブル'cars','bikes','trains'にアクセス/変更するための DBI/SQL メソッド
 #
 print $dbh->func( 'cars', 'HTMLtable', 'ad_export');

または
 use DBI;
 my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
 $dbh->func( 'Pipe', 'data.pipe', 'XML', 'data.xml', 'ad_convert');

または
 (たくさんの他のデータフォーマットの数多くの組み合わせ。下記を参照)


説明

DBD::AnyData モジュールは多くのフォーマット、多くのソースにはいったデータへのDBI/SQLインターフェースを提供します。

現在のところ、サポートされているフォーマットには一般的なフォーマットのフラットファイル(CSV、固定長、タブもしくはパイプで"区切られた"ものなど)、特定のフォーマット(passwdファイル、webログなど)、フォーマットの他の種類(XML、Mp3、HTMLテブル)、そしてある種の操作ではすべてのDBIがアクセス可能なデータベースを含んでいます。サポートされるフォーマットの数は急速に大きくなり続けるでしょう。というのもオープンなAPIによりAnyDataに組み込むことができる追加のフォマーット・パーサーを作成するのを簡単にしているからです。

これらの多様なフォーマットのデータはローカル・ファイル、リモート・ファイル、文字列や配列といったperlデータ構造体からすることができます。

データのフォーマットやソースに関係なく、すべての標準的なDBIメソッドやSQL文法のサブセットを使ってアクセスそして/あるいは変更されます。

標準的なファイルへのデータベース・アクセスに加えて、メモリ上のテーブルもサポートしています。これにより一時的なビューを作成したり;いくつかのソースのデータを組み合わせたり;データベース・システムの早いプロトタイプをしたり;そしてデータをサポートされているフォーマットのいずれかで表示あるいは保存したり(例えばCSVファイルに入っているデータをHTMLテーブルで表示する)といったことが可能です。これらメモリ上のテーブルはDBIデータベースやどんなフォーマットのファイルでも組み合わせからも作成することができます。これはperlデータ構造からも作ることができます。つまりファイル・アクセスやrdbmsバックエンドがまったくなしに、データベース・システムを早くプロトタイプをすることができます。

このモジュールはサポートされているフォーマット間でのファイルの変換をサポートしています。(例えばMySQLやOracleからselectされたデータをXMLファイルに保存するなど)

機能のほんのちょっとした例を以下に示します:

    # PASSWDファイルからのデータの取得
    #
    $dbh->func( 'users', 'Passwd', '/etc/passwd', 'ad_catalog');
    my $sth = $dbh->prepare("SELECT username,homedir,GID FROM users');

    # 新しい行をCSVファイルに挿入
    #
    $dbh->func( 'cars', 'CSV', 'cars.csv', 'ad_catalog');
    $dbh->do("INSERT INTO cars VALUES ('Honda','Odyssey')");

    # リモートにあるXMLファイルを読み込み、HTMLテーブルとして出力
    #
    print $dbh->func( 'XML', $url, 'HTMLtable', 'ad_convert');

    # MySQLデータベースをXMLに変換し、新しいファイルに保存
    #
    $dbh->func( 'DBI', $mysql_dbh, 'XML', 'data.xml', 'ad_convert');

    # Oracleデータベースとタブで区切られたファイルからのデータがVIEWを作成し、CREATE AND ACCESS A VIEW CONTAINING DATA FROM AN ORACLE DATABASE
    # 入ったVIEWを作成し、アクセス
    #
    $dbh->func( 'combo', 'DBI', $oracle_dbh, 'ad_import');
    $dbh->func( 'combo', 'Tab', 'data.tab', 'ad_import');
    my $sth = $dbh->prepare("SELECT * FROM combo");


インストール

DBD::AnyDataを使いたければ、以下のすべてのモジュールをインストールする必要があります。
すべてがCPANから利用できますし、大半はActiveStateから利用できます。
  * DBI
  * SQL::Statement
  * DBD::File
  * AnyData
  * DBD::AnyData

 注意: DBD::File はDBD::CSVディストリビューションの一部です。
 いくつかの高等な機能は追加のモジュールが必要です:

 * リモート・ファイルアクセスには LWP (libwww バンドル)が必要です。
 * XML アクセスには XML::Parser と XML::Twig が必要です。
 * HTML テーブルアクセスは HTML::Parser と HTML::TableExtractが必要です。
 * HTML テーブルの書き込みには CGI が必要です。

 AnyData と DBD::AnyData そのものはどちらも標準的なmakefile、make、make test、
 make installで、あるいは単に適切なディレクトリにそれらをコピーすることによって
 インストールすることができます。他のモジュールは完全なmakeプロセスやあらかじめ
 コンパイルされているバイナリを必要とします。

クイック・スタート

基本

スクリプトでDBD::AnyDataを使うには主に4つのステップがあります

 1. DBIモジュールを使いたいことを指定
 2. データベース・ハンドルの作成
 3. 欲しいテーブル、ファイル、フォーマットを指定
 4. データをアクセスそして/または変更のためのDBI/SQLコマンドを使用

ステップ #1, #2, そして #3 は、それぞれ1行程度の小さなものになります。

ステップ#3 と #4 は、状況によっては省略することができます。下記の"メモリ上のデータの動き"と"データ変換"のセクションをご覧ください。

ステップ #1 : DBIモジュールを使いたいことを指定

 このステップは常に同じです:スクリプトの先頭にこれをおいておくだけです:
     use DBI;
ステップ #2 データベース・ハンドルの作成
 このステップは必要によってちょっとずつ違うかもしれませんが、通常は以下の通りです:
 
     my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');

他の接続の形式については、下記のセクション "接続オプション"をご覧ください。1つ以上のデータベース・ハンドルを作る場合については下記のセクション "複数データベースの使い方"をご覧ください。

ステップ #3 : テーブル、ファイル、フォーマットの指定

このステップではDBD::AnyData独特のいくつかのメソッドの1つを使います。これらのメソッドはfunc()呼び出しをおこない、最後のパラメータとしてメソッドの名前を指定するために、#2で作成されたデータベース・ハンドルを使います。例えば'ad_catalog'メソッドは以下のように呼ばれます:
 $dbh->func( ..., 'ad_catalog')

 ad_catalog() メソッドは3つの必須のパラメータと1つのオプションのパラメータを取ります:

     $dbh->func( $table, $format, $file, $flags, 'ad_catalog')

     $table  = SQLコマンドでTABLEとして使う名前
     $format = データのフォーマット('XML', 'CSV', 'Fixed', など)
     $file   = データが入っているローカルまたはリモートファイル
     $flags  = データフォーマットによっては必要となるオプションのフラグのハッシュ
 例:

    $dbh->func( 'cars', 'XML', 'cars.xml', 'ad_catalog' )

これはテーブル名を'cars'が、ファイル'cars,xml'に格納されたXMLデータにアクセスするために使われることを指定します。

1度catalogコマンドを発行すれば、$fileの中のデータにアクセスあるいは変更するためにSQLコマンドで名前$tableを使うことができます。catalogはテーブル/ファイル/フォーマットの組み合わせを指定するために1度だけ必要で、無数の処理コマンドのために使うことができます。

ステップ #4 : データのアクセスそして/または変更のためにDBI/SQLコマンドの使用

 DBD::AnyDataは標準のDBIメソッドのすべてとSQL文法のサブセットをサポーとしています。
サポートされているSQLについては、下記のセクション "SQL文法"をご覧ください。DBIコマンド
の詳しい説明についてはDBIドキュメントをご覧ください。
 テーブルを作ったり削除したり、データを挿入、削除j、更新するためにdo()メソッドを
使うことができます:
    $dbh->do("CREATE TABLE ... )
    $dbh->do("DROP TABLE ... )
    $dbh->do("INSERT INTO ... )
    $dbh->do("UPDATE ... )
    $dbh->do("DELETE ... )

 データのアクセスのためにprepare()、execute()そしてfetch()メソッドの組み合わせを
使うことができます:

    my $sth = $dbh->prepare("SELECT * FROM cars WHERE make = 'Honda'");
    $sth->execute();
    while (my $row = $sth->fetchrow_hashref){
        print $row->{model};
    }


すべてを一緒に
 これは"cars.csv"というファイルにCSVフォーマットで格納されたデータに
アクセスするために必要な完全なスクリプトです。これはデータベースの
"make"と"model"カラムからすべてのデータを出力します。
 1.  use DBI;
 2.  my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
 3.  $dbh->func( 'cars', 'CSV', 'cars.csv' 'ad_catalog');
 4.  my $sth = $dbh->prepare("SELECT make, model FROM cars");
 5.  $sth->execute();
 6.  while (my $row = $sth->fetch) {
 7.      print "@$row\n";
 8.  }

 行 1 DBIモジュールを使うことを指定します。
 行 2 データベース・ハンドルの作成
 行 3 テーブル、フォーマットそしてデータが入っているファイルを指定します
 行 4 から 8 DBIとSQLを使ってファイルの中のデータいアクセスします。

テーブル構造のカスタマイズ

データベースからのデータの読み込み方決めるとき、DBD::AnyData は数々のデフォルトを使います、そして多くの場合、これらのデフォルトはすべてあなたに必要なものです。しかしあなたの使っているフォーマットやデータベースによっては、カラム命やレコード・セパレータなどのような、他の機能を指定する必要があるかもしれません。

この追加の情報をad_catalogや他のDBD::AnyDataメソッドの$flagsパラメータで指定することができます。$flagsは常に配列へのリファレンスです、つまり1つまたは複数のキーと値のペアが=>でつなげられ、カンマによって分けられ、曲括弧で囲まれます:

    $flags = { key1 => value1, key2 => value2 ... }
    あるいはメソッド呼び出しで:

    $dbh->func( $table, $format, $file, { key1=>val1, ... }, 'ad_catalog');
  ※訳者注:原文では{ key1=>,val1 ... },となっていたが間違い

カラム名

いくつかのフォーマットはあらかじめ決まったカラム名を持っています:
    Passwd  username
            passwd
            UID
            GID
            fullname
            homedir
            shell

    Weblog  remotehost
            usernname
            authuser
            date
            request
            status
            bytes
            referer
            client

    Mp3     song
            artist
            album
            year
            genre
            filename
            filesize

他のフォーマットでのカラム命はデータベースそのもので指定することもできますし、$flagsパラメータで与えることもできます。

もしデータベースでカラム名が指定されると、データベースの最初のレコードから取得されます。例えば、CSV(Comma Separated Value)ファイルや固定長ファイルでは、デフォルトではテーブルの最初の行をカラム名のリストとして扱います。HTMLテーブルでは、デフォルトは最初のテーブルの最初の<tr>を見ます。XMLファイルではデフォルトはすべての属性名、最初の初期化タグを除いた最初のタグに入っているすべてのCDATAとPCDATA要素を使います。

ほとんどの場合、カラム名を定義する最初のレコードはテーブルの残りと同じフォーマットです。例えばCSVファイルでのCSV文字列。タブ区切りファイルでタブで区切られた文字列など。この1つの例外は固定長ファイルです、ファイルの先頭行には固定長のリストではなく、カラム名の*カンマ区切り*のリストが入れることができます。HTMLテーブルとXMLもカラム名を選択するために他のフラグを使います(例えばテーブルの番号とかチェックするツリーでの深さ)。デフォルトがどのように選択されるかについてのさらなる詳細は、それぞれのフォーマットのドキュメントをご覧ください。

ほとんどのフォーマットでは、カラム名がファイルの最初のレコードにカラム名が入っていなければ、$flagsパラメータでカンマ区切りのリストとして指定することができます。

    $dbh->func(
        'cars',
        'Tab',
        'data.tab',
        { col_names => 'make,model,year' },
    'ad_catalog')

サポートされているフォーマット

CSV, タブ, パイプ, Ini, パラグラフ

固定長

固定長フォーマット・ファイル(各カラムは指定された長さ)はいくつかの点で独特です。まず最初に言わなければならないことは、ファイルそのものにカラム名を入れようと思えば、そのファイルの先頭行に*カンマ区切り*の文字列で入れなければなりません。

次に、'pattern'という必須のフラグがあります。固定長フォーマットを使いたいときにはいつでも使わなければなりません。kのフラグはカラムの幅を指定します。これはパターンを指定するために標準のPerl pack/unpackの書き方を使います。さらなる詳細については、Perlドキュメントをご覧ください。ほとんどの場合、単に先頭を'A'、その後にカラムの長さをつけます: 

  { pattern => 'A10 A12 A4' }

これはテーブルには10、12、14文字の3つのフィールドが入っているということを指定します。

XML 

HTMLテーブル

DBI

DBD::AnyData はすべてのDBIデータベースをメモリにインポートすることをサポートしています。そしてすべてのDBIデータベースを他のAnyDataフォーマットのいずれかに変換することもできます。

'DBI'というフォーマット名を使い、filenameの代わりに、ad_import呼び出しにあなたが使うデータベースへの接続と、SQL SELECTステートメントを指定して渡します。

Use the format name 'DBI', and instead of a filename, pass the ad_import call a connection in whatever database you are using, and specify a SQL SELECT statement:

  my $dbh = DBI->connect('dbi:AnyData:(RaiseError=>1)');
  $dbh->func(
      'table1',
      'DBI',
      DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
      {sql=>"SELECT make, model FROM cars WHERE make = 'honda'"},
  'ad_import');

上記のようにするとMySQLデータベースから(名前をつけられたカラムと選択された行だけを選んだ)ビューをAnyDataのメモリ上のテーブルにインポートします。これはメモリ上で問い合わせ、そして/あるいは変更することができます。そしてXMLのようなそのほかのフォーマットで表示あるいは格納することができます。

パラメータの配列リファレンスをもった追加のフラグを渡すことにより、SQL呼び出しのためにbind_parameters形式を使うことができます:

     {
         sql     => "SELECT make,model FROM CARS WHERE make = ?"
         params  => ['honda']
     }

ORACLEやMySQLのようにDBIでアクセス可能なデータベースからXMLのようなAnyDataフォーマットの1つに変換するためにはデータベースにtable_nameフラグも入れなければなりません:

  my $dbh = DBI->connect('dbi:AnyData:(RaiseError=>1)');
  $dbh->func(
      'DBI',
      DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
      'XML',
      'cars.xml',
      {table_name=>'cars'},
  'ad_convert');

あるいは同じデータを格納することなしに、HTMLテーブルに出力します:

  my $dbh = DBI->connect('dbi:AnyData:(RaiseError=>1)');
  print $dbh->func(
      'DBI',
      DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
      'HTMLtable',
      undef,
      {table_name=>'cars'},
  'ad_convert');

ad_convert() メドッソはデータベース全体に機能します。データベースの選択されている一部分だけを変換する必要があれば、SELECT節をもったad_import()を使い、そしてそれを新しいフォーマットにad_export()します。

ad_importメソッドはデフォルトではインポートされたデータベースのための接続を閉じます。他のデータベースのために、そのハンドルを使い続けたければ、フラグ{keep_connection=>1}を渡してください:

  my $dbh       = DBI->connect('dbi:AnyData:(RaiseError=>1)');
  my $mysql_dbh = DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
  $dbh->func(
      'cars',
      'DBI',
      $mysql_dbh,
      { keep_connection=>1 },
  'ad_import');
  #...
  $mysql_dbh->disconnect;

Passwd, Weblog, Mp3

その他のフォーマット 

DBD::AnyDataは他の人が他のフォーマットのためのサポートを作れるようなオープンAPIをサポートしています。 つまり、サポートされるフォーマットのリストは大きくなり続けるだろうということです。現在Wes Hardaker がAnyData::Format::SNMP のために働いていますし、Earl Cahill がAnyData::Format::Storableのために働いています。新しいフォーマット・モジュールについて働らくことに興味を持ったら、私に連絡してください (mailto:jeff@vpservices.com)。

 


詳細情報

フォーマット間での変換

$dbh->func(...,'ad_convert') メソッドは、DBD::AnyDataによってサポートされている任意のデータフォーマット間での1ステップによる変換の方法を提供します。例えば、CSVファイルを読み込み、XMLファイルに保存したり、その反対など。詳細については下記のセクション "変換(convert)"をご覧ください。ORACLEまたはMySQLやその他のデータベースからXML、CSV、もしくは任意のDBD::AnyDataフォーマットへ変換することに関する情報についてはセクション "他のDBIデータベースと機能する"をご覧ください。

リモート・ファイルの使用

FTPまたはHTTPによってアクセスできるリモートのファイルを直接DBD::AnyDataのメモリ上データベースに、'ad_import'を使ってインポートしたり、ad_convertを使ってリモート・ファイルを文字列として出力したり、ローカルファイルに保存したりといったことができます。もしad_importまたはad_convetの$fileパラメータが"ftp"または"http"から始まっていると、DBD::AnyDataは見えないところでLWPを呼び出し、ファイルを取り出します。

これはリモート・ファイルを取り出し、そのXMLを解析し、DBI/SQLで問い合わせたり、ローカルファイルに保存できるメモリ上のテーブルを提供します:

    $dbh->func(
        'news',
        'XML',
        'http://www.somewhere.org/files/news.xml',
    'ad_import');

これはリモート・ファイルを取り出し、そのXMLを解析し、HTMLテーブルとして出力します:

    print $dbh->func(
        'XML',
        'http://www.somewhere.org/files/news.xml',
        'HTMLtable',
    'ad_convert');


もしリモート・ファイルが認証を必要とするならば、$flagsパラメータに"user"と"pass"のための値を入れることができます:

    $dbh->func(
        'news',
        'XML',
        'http://www.somewhere.org/news.xml',
        { user => 'fred', passwd => 'x9y77d' },
    'ad_import');

メモリ上のテーブルで機能する

通常のファイルに記録されるデータベースに加え、DBD::AnyDataはメモリ上に格納され、変更されるデータベースをサポートします。データベースに単に問い合わせてクローズしたり、ad_exportメソッドを使ってデータを画面に表示したり、ファイルに保存することができます。メモリ上のデータベースを使いたいという理由には以下のものを含めていくつもあります:

プロトタイピング:ファイルやrdbmsへのアクセスを一切必要とせず、文字列、配列またはスクリプトのDATAセクションから、早くデータベースを作る。

ビューの作成:ORACLEやMySQLデータベース一般から、選択されたカラム、選択された行を取り出し、フルのデータベースを使うのではなく、メモリ上で使う。

複数のフォーマットのデータの組み合わせ:例えばXMLファイルやOracleデータベースそしてCSVファイルから選択されたカラム、選択された行をインポートすることにより、1つのメモリ上テーブルを作成する。

ロールバック/コミット:メモリ上データベースに複数の変更をすることができ、そしてそれらの変更が成功か失敗かによって、その変更をディスクに保存するエクスポートを使ってコミットするか、実質的にデータベースをインポートの前の状態に戻すようエクスポートを飛ばす。

メモリ上テーブルはDBI/SQLコマンドによって変更することができます。そして任意のAnyDataフォーマットで画面上に出力したり、ディスクに保存することができます(下記のad_exportメソッドをご覧ください)

メモリ上テーブルはいくつかの方法で作られます:

 1. 1つまたは複数のローカルもしくはリモートのファイルからテーブルを作る
 2. 文字列からテーブルを作る
 3. 配列からテーブルを作る
 4. DBI/SQLコマンドを使って、テーブルを作る

ローカルもしくはリモート・ファイルからメモリ上テーブルを作る

指定されたフォーマットの文字列からメモリ上テーブルを作ることができます。
注意: 文字列は鍵括弧で囲まれていなければなりません。

これはCSVファイルをメモリ上テーブルに読み込みます。特にad_exportを使ってテーブルをファイルに保存しなければ、さらなるアクセスと変更はファイルアクセスなしにメモリ上で行われます。

    # ローカルファイルからテーブルを作成
    #
    $dbh->func( 'test2', 'CSV', $filename, 'ad_import');

    # リモート・ファイルからテーブルを作成
    #
    $dbh->func( 'test2', 'CSV', $url, 'ad_import');

リモート・ファイルの使い方の詳細については、"リモート・ファイルアクセス"についてのセクションをご覧ください。

文字列からメモリ上テーブルを作成する

指定されたフォーマットの文字列からメモリ上テーブルを作ることができます。
注意: 文字列は鍵括弧で囲まれていなければなりません。

この例はCSV文字列からメモリ上テーブルを作成します:

 
    # CSV文字列からテーブルを作る
    #
    $dbh->func( 'test2', 'CSV',
         ["id,phrase\n1,foo\n2,bar"],
    'ad_import');

スクリプトのDATAセクションからメモリ上テーブルを作る

Perlはマーカー__END__の後にテキストをおいておけば、DATA配列を使ったファイルからのようにそのテキストにアクセスできるという、本当にクールな機能を持っています。これはクイック・プロトタイピングにはとっても素晴らしいことになります。

例えばこれは小さなテーブルを構築し、アクセスし、"Just Another Perl Hacker!"と出力するという一通りのスクリプトです:

     use DBI;
     my $dbh=DBI->connect('dbi:AnyData(RaiseError=>1):');
     $dbh->func( 'test', 'XML',  [<DATA>],  'ad_import');
     print $dbh->selectcol_arrayref(qq{
         SELECT phrase FROM test WHERE id = 2
     })->[0];
     __END__
     <phrases>
         <phrase id="1">Hello World!</phrase>
         <phrase id="2">Just Another Perl Hacker!</phrase>
     </phrases>

DATAセクションで任意の大きさのサポートされている任意のフォーマットについて同じ考えをすることができます。

配列からメモリ上テーブルを作る

配列からもメモリ上テーブルを作ることができます。もしくはさらにテクニカルですが、配列へのリファレンスからも。配列はそれら自体が行の値の配列へのリファレンスである行を構成しなければなりません。最初の行はカラム名でなければなりません。

 例:

   # 配列からテーブルを作る
   #
   $dbh->func( 'test3', 'ARRAY',
               [
                  ['id','phrase'],
                  [1,'foo'],
                  [2,'bar']
               ],
   'ad_import');


DBI/SQLコマンドからメモリ上テーブルを作る

ファイルにテーブル名を関連づけるためにad_catalogやad_importを使わなければ、テーブルはメモリ上テーブルになります。そのためDBI/SQLコマンドを使えばすぐに始めることができます:

    # DBI/SQLコマンドからテーブルを作る
    #
    use DBI;
    my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
    $dbh->do("CREATE TABLE test (id TEXT,phrase TEXT)");
    $dbh->do("INSERT INTO test VALUES (1,'foo')");
    $dbh->do("INSERT INTO test VALUES (2,'bar')");
    $dbh->do("UPDATE test SET phrase='baz' WHERE id = '2'");
    $dbh->do("DELETE FROM test WHERE id = '1'");

複数のデータベースを使う、ジョインのシュミレーション

任意の数のデータベースを1つのスクリプトでアクセスできます。そしてさまざまなデータ・フォーマットを混ぜ、マッチさせることができます。

例えばこれは2つのデータ・フォーマットから2つのメモリ上テーブルを作ります:

 $dbh->func( 'classes', 'CSV', 'classes.csv' 'ad_import');
 $dbh->func( 'profs',   'XML', 'profs.xml',  'ad_import');

同様にいくつかの異なるフォーマットから1つのテーブルへカラムをインポートすることができます。例えば、これはXMLファイルとパイプ区切りファイルからデータをインポートし、1つのメモリ上データベースにデータをインポートします。それぞれのインポートからのデータが1つのテーブルに追加されるので、$tableパラメータが各呼び出しで同じであることに注意してください。

 $dbh->func( 'test', 'XML',  [$xmlStr],  'ad_import');
 $dbh->func( 'test', 'CSV',  [$csvStr],  'ad_import');
 $dbh->func( 'test', 'Pipe', [$pipeStr], 'ad_import');

このように複数のテーブルを1つのテーブルにインポートすると、出来上がったテーブルはlookup_keyフラグを与えないとクロス・ジョインになります。もしlookup_keyが与えられると、出来上がったテーブルはそのキー・カラムで完全なアウター・ジョインになります。この機能は時間の関係から実験的なものですが、キー・カラム以外に同じ複数のテーブルで同じ名前のカラムがなければ思ったとおりに動くでしょう。インポートするまえに空のなにもないテーブルを作ることにより、ジョインされたテーブルが特定のカラムだけを持つように指定することができます。sqlフラグで特定の行だけを入れるように指定することができます。例えば:

  $dbh->func('test','ARRAY',[],{col_names=>'foo,bar'baz'}, 'ad_import');
  $dbh->func('test','XML',$file1,{lookup_key=>'baz'},'ad_import');
  $dbh->func('test','CSV',$file1,{lookup_key=>'baz'},'ad_import');

DBD::AnyData は現在のところ、1つのSQLステートメントに複数のテーブルを使うことをサポートしていません。しかし複数のテーブルを使い、異なるSQLステートメントで別々に問い合わせることができます。つまり2つのステートメント・ハンドルを作り、最初のハンドルからの値を2番目のハンドルのためのlookupキーとして使うことにより、ジョインをシュミレートすることができるということです。このようにして:

 $dbh->func( 'classes', 'CSV', 'classes.csv' 'ad_import');
 $dbh->func( 'profs',   'XML', 'profs.xml',  'ad_import');
 my $classes_sth = $dbh->prepare( "SELECT pid,title FROM classes" );
 my $profs_sth   = $dbh->prepare( "SELECT name FROM profs WHERE pid = ?" );
 $classes_sth->execute;
 while (my($pid,$class_title) = $classes_sth->fetchrow_array) {
     $profs_sth->execute($pid);
     my $row = $profs_sth->fetchrow_arrayref;
     my $prof_name = $row ? $row->[0] : '';
     print "$class_title : $prof_name\n";
 }

これは以下のものと同じ結果を作ります:

     SELECT classes.title,profs.name FROM classes,profs WHERE pid = pid
 

リファレンス

DBD::AnyDataメソッドの概要

DBD::AnyDataでは他のドライバにはない5つのメソッドを使うことができます:

     ad_catalog  DBI/SQLのために使われるファイルを指定します
                 連続したファイルアクセス 

     ad_import   データをメモリ上テーブルにインポートします

     ad_export   メモリ上テーブルからファイルへデータをエクスポートします

     ad_clear    メモリ上テーブルをクリアします(メモリから削除します)

     ad_convert  データをあるフォーマットから他のフォーマットに変換し、
                 新しいファイルに保存するか、それを文字列として返します

これらのメソッドはDBI func()を使って呼ばれます、例えば:

     $dbh->func( $table, $format, 'ad_export');

各種のメソッドのためのパラメータを以下に示します:

     $dbh->func( $table, $format, $file, $flags, 'ad_catalog');
     $dbh->func( $table, $format, $data, $flags, 'ad_import');

     $dbh->func( $source_format, $source_data,
                 $target_format, $target_file,
                 $source_flags,  $target_flags,
     'ad_convert');
     $dbh->func( $table, $format, $file, $flags, 'ad_export');
     $dbh->func( $table, 'ad_clear' );
     

$tableは適切なSQLテーブル名です

$formatはAnyDataフォーマットの1つです('XML'、'CSV'など)

$fileはローカル・コンピュータ上の(相対または絶対の)適切なファイル名です

$flagsはキー/値の組が入ったハッシュ・リファレンスです。例えば

    { col_names => 'make,model,year', pattern => 'A10 A12 A4' }

$dataは以下のいずれか1つです:

* ローカル・コンピュータ上の適切なファイル名(相対または絶対)
* 適切な絶対FTPまたはHTTP URL
* 最初にカラム名が入った行の配列リファレンスの入った配列リファレンス
        [
          ['make','model'],
          ['Honda','Odyssy'],
          ['Ford','Suburban'],
        ]
* 指定されたフォーマットの文字列が入った配列リファレンス
        CSV  :  ["id,phrase\n1,foo\n2,bar"]
        Pipe :  ["id|phrase\n1|foo\n2|bar"]

* ファイルのDATAセクションへのリファレンス
         [<DATA>]
* DBIデータベースハンドル
         DBI->connect('dbi:mysql:database=...)

ad_catalog メソッドはファイルをデータベースとして扱うための標準的な方法です。データにアクセスするたびに、それはファイルから読み込み、そしてデータを変更するたびに、それはファイルに書き込みます。明示的にそれを要求しなければ、ファイル全体はメモリ上にすべて読み込まれるなんてことはありません。

ad_importメソッドはデータをローカルまたはリモートファイルから、DBIがアクセスできるデータベースのいずれかから、配列や文字列のようなperlデータ構造体からデータをいポートすることができます。テーブル全体もしくは指定したカラムや行だけをインポートすることができます。もしデータがファイルからインポートされると、ad_importを読んだときに、選択したデータのすべてはメモリ上に読み込まれます。そのためこれはメモリにフィットするよりも大きいSELECTでされるべきではありません:-)。すべてのアクセス、変更はメモリ上で行われます。もし変更の結果を保存したければ、明示的にad_exportする必要があります。

Not all formats and data sources will work with all methods. Here is a summary of what will work. "all sources" includes local files, remote files, any DBI accessible database, perl arrayrefs, perl strings.

 Import From   all formats, all sources
 Convert From  all formats, all sources
 Convert To    all formats except DBI, local files, arrays or strings only
 Export To     all formats except DBI, local files, arrays or strings only
 Catalog       all formats except DBI, XML, HTMLtable, Mp3, ARRAY,
               local files only

connect

DBI->connect 呼び出し

ad_catalog

 目的:

    テーブル名、データフォーマット、ファイルの関連付けを作成する。
 書き方:

     $dbh->func( $table, $format, $file, $flags, 'ad_catalog' )
 パラメータ:

     $table  = SQLコマンドで使われるテーブル名

     $format = AnyDataフォーマット('XML','CSV'など)

     $file   = ローカルファイルの名前(フルパスあるいは相対)

     $flags  = オプションのカラム名または他の値

 例:

    これはテーブル'cars'に対するすべてののDBI/SQLステートメントが
  ファイル'/users/me/data.xml'のなかのXMLデータにアクセスあるいは/または
  変更することを指定します。
       $dbh->func( 'cars', 'XML', '/usrs/me/data.xml', 'ad_catalog' )

 注意:

   formatはDBI、XML、HTMLtable、MP3を*除く*任意のAnyDataフォーマットにすることができます。 

ad_import

 目的:

     任意のソースの任意のフォーマットからのデータをメモリ上テーブルにインポートする。

 書き方:

     $dbh->func( $table, $format, $data_source, $flags, 'ad_import' )

 注意:

     $table       = SQLコマンドで使われるテーブル名

     $format      = AnyDataフォーマット('XML','CSV'など)

     $data_source = $ファイル名
             または $URL
             または [$文字列]
             または [<DATA>]
             または $配列の配列へのリファレンス
             または $DBIデータベース・ハンドル

     ($data_sourceの詳細についてはセクション"データ・ソース"をご覧ください)

 例:

     $dbh->func( 'cars', 'XML', '/usrs/me/data.xml', 'ad_import' )

     さらなる例についてはセクション "メモリ上テーブル"、"リモートファイル"、
     "DBIデータベース"をご覧ください。

ad_export

 目的:

     メモリ上テーブルを指定されたフォーマットに変換し、ファイルに保存したり、
     文字列として返したりします。

 書き方:

     $dbh->func( $table, $format, $file, $flags, 'ad_export' )

     または

     my $string = $dbh->func( $table, $format, $flags, 'ad_export' )

 パラメータ:

     $table  = エスクポートするメモリ上テーブルの名前

     $format = AnyDataフォーマット('XML','CSV'など)

     $file   = ローカルファイルの名前(フルパスあるいは相対)

 例:

     テーブルをXMLファイルとして保存する:

        $dbh->func( 'cars', 'XML', '/usrs/me/data.xml', 'ad_export' )
     テーブルをHTMLテーブルとして出力

         print $dbh->func( 'cars', 'HTMLtable', 'ad_export' )

ad_convert

 目的:

     1つのフォーマットから別のフォーマットにデータを変換し、
   文字列として返したり、新しいフォーマットでファイルに保存したりします。
 書き方:

   my $str = $dbh->func(
       $source_format,
       $data_source
       $target_format,
       $source_flags,
       $target_flags,
   'ad_convert' );

   または

   $dbh->func(
       $source_format,
       $data_source
       $target_format,
       $target_file,
       $source_flags,
       $target_flags,
   'ad_convert' );

 パラメータ:

     $source_format = 元になるDBのAnyDataフォーマット('XML','CSV'など)

     $target_format = ターゲットになるDBのAnyDataフォーマット('XML','CSV'など)

     $target_file  = 変換されたデータが格納されるファイルの名前

     $data_source = $ファイル名
             または $URL
             または [$文字列]
             または [<DATA>]
             または $配列の配列へのリファレンス
             または $DBIデータベース・ハンドル

     ($data_sourceの詳細についてはセクション"データ・ソース"をご覧ください)
 例:

 # CSVファイルをXMLファイルに変換する
 #
 $dbh->func( 'CSV', 'data.csv', 'XML', 'data.xml', 'ad_convert');

 # 配列リファレンスをHTMLテーブルに変換し、それを出力
 #
 print $dbh->func( 'ARRAY', $aryref, 'HTMLtable', 'ad_convert');

 # 配列リファレンスをXMLに変換し、それをファイルに保存
 #
 $dbh->func( 'ARRAY', $aryref, 'XML', 'data.xml', 'ad_convert');

 # MySQLデータベースから選択したものをXMLに変換し、
 # ファイルに保存
 #
 $dbh->func(
     'DBI',
     $mysql_dbh,
     'XML',
     'data.xml',
     {sql=>"SELECT make,model FROM CARS where year > 1996"}
 'ad_convert');

 注意

 フォーマット'DBI'(DBIがアクセスできる任意のデータベース)は変換の元として
 使うことができますが、ターゲットとしては使えません。 

 フォーマット'ARRA'は変換の元が配列へのリファレンスであることを示すために
 使うことができます。もしくは変換結果が配列リファレンスとして返されるように
 使うことができます。(配列リファレンスの構造については "メモリ上テーブルの
 を利用する" をご覧ください)

データソース

 ad_import と ad_convert メソッドはローカル・ファイル、リモート・ファイル
 文字列、配列、DBIがアクセスできる任意のデータベース、スクリプトのDATA
 セクションなど多くのソースからデータを取ることができます。
 
 ad_importとad_convertに渡される$data_sourceパラメータは
 特定のデータソースによって異なります。以下をご覧ください。
 ローカル・ファイル

     ローカル・ファイル名が入った文字列。フル・パスまたはパスまたは
     現在定義されているf_dirからの相対(?をご覧ください);

     e.g. '/users/me/data.xml'

 リモート・ファイル

     データのURLが入った文字列。'ftp://'または'http://'で始まらなければなりません。

     e.g. 'http://www.somewhere.org/misc/news.xml'

 配列の配列

     データの配列へのリファレンス。データの各行は値の行へのリファレンスです。
     先頭行はカラム名になります。
     
     E.G.:

        [
          ['make','model'],
          ['Honda','Odyssy'],
          ['Ford','Suburban'],
        ]

  文字列

     すべてのフィールドとレコード区切りが入った、指定されたフォーマットの
     文字列。文字列は配列リファレンスで行だけが入っていなければなりません。
     (つまり鍵括弧でくくられなければなりません)
     e.g. CSV文字列

         ["id,phrase\n1,foo\n2,bar"]

     またはパイプで区切られた文字列

         ["id|phrase\n1|foo\n2|bar"]

  ファイルのDATAセクション

      スクリプトでの__END__の後ろの行から得られる配列へのリファレンス。

         [<DATA>]

  DBIデータベース

      指定されたrdbmsのためのデータベース・ハンドル。

      DBI->connect('dbi:mysql:database=...)

ad_clear

 目的:

     Clears an in-memory table (deletes it from memory)

 書き方:

     $dbh->func( $table, 'ad_clear' )

 パラメータ:

     $table  = クリアするメモリ上テーブルの名前

 注意:

 それらを作るために使われたデータベース・ハンドルがスコープから外れると
 メモリ上テーブルはメモリから自動的に削除されます。作成するために使われた
 データベースハンドルに$dbh->disconnect()を呼び出しても削除されます。
 ad_clearメソッドはデータベース・ハンドルを使い続けたいけれども、
 指定されたテーブルはもう必要がないときに、メモリを解放するための方法です。
 他の(すべての?)Perlメモリ操作と同じように、これはPerlスクリプトの残り
 ために解放はしますが、スクリプトにより使われえているシステムメモリ全体の
 量を減らすわけではありません。

SQL文法

 現在、限られたSQLコマンドサブセットだけがサポートされています。
 各コマンドでは1つのテーブルだけが使われます。つまり、*ジョイン*は
 ないということです。しかし上記のセクションを見ていただくとおり、
 ジョインのシュミレーションはあります。数ヵ月後には追加のSQL機能が追加
 されるでしょう。ですからusenetやdbi-usersメーリングリストでのANNOUNCE
 メッセージにご注目ください(下記 "さらなるヘルプを得るには"もご覧ください)

 これは簡単長いようです。これについてのさらに完全な説明はSQL::Statement
 のドキュメントをご覧ください。
       CREATE  TABLE $table
                     ( $col1 $type1, ..., $colN $typeN,
                     [ PRIMARY KEY ($col1, ... $colM) ] )

        DROP  TABLE  $table

        INSERT  INTO $table
                     [ ( $col1, ..., $colN ) ]
                     VALUES ( $val1, ... $valN )

        DELETE  FROM $table
                     [ WHERE $wclause ]

        UPDATE  $table
                     SET $col1 = $val1, ... $colN = $valN
                     [ WHERE $wclause ]
        SELECT  [DISTINCT] $col1, ... $colN
                     FROM $table
                     [ WHERE $wclause ] 
                     [ ORDER BY $ocol1 [ASC|DESC], ... $ocolM [ASC|DESC] ]

           $wclause  [NOT] $col $op $val|$col
                     [ AND|OR $wclause2 ... AND|OR $wclauseN ]

                $op  = |  <> |  < | > | <= | >= 
                     | IS NULL | IS NOT NULL | LIKE | CLIKE

 "CLIKE"演算子は"LIKE"とまったく同じです。しかし大文字小文字を区別しません。

さらなるヘルプを得るには


謝辞(ACKNOWLEDGEMENTS)

(原文のまま)

Many people have contributed ideas and code, found bugs, and generally been supportive including Tom Lowery, Andy Duncan, Randal Schwartz, Michel Rodriguez, Wes Hardraker, Bob Starr, Earl Cahill, Bryan Fife, Matt Sisk, Matthew Wickline, Wolfgang Weisseberg. Thanks to Jochen Weidmann for DBD::File and SQL::Statement and of course Tim Bunce and Alligator Descartes for DBI and its documentation.


作者そして著作権(AUTHOR & COPYRIGHT)

(原文のまま)
 copyright 2000, Jeff Zucker <jeff@vpservices.com>
 all rights reserved

ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。