小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

SQL-SELECT文からPerl-HASH関数へ(Select2Hash)

PerlからOLEモジュールを使って、SQLServerからデータをSELECTするときに、そのデータを、行は配列、列はハッシュとして、Perlでの「ハッシュの配列」に格納すると取得データのアクセスが便利です。
以下のSelect2Hash関数は、そのような関数です。

use strict;
my @result = &Select2Hash("SELECT UserName, UserTel FROM UserTable");
for (my $i = 0; $i <= $#result; $i++){
    print $result[$i]{UserName}, "\n";
    print $result[$i]{UserTel}, "\n";
}
sub Select2Hash {
# 本ルーチンによるSELECT文フォーマット制限
# 1,SELECTとFROMを必ず同一行に記述する。(SELECT aaa, bbb, ccc FROM……)
# 2,選択項目でエイリアスがある時は必ずASキーワードを使用する(SELECT X.aaa AS xxx, ……)
# 3,選択項目は、アスター「*」は不可(選択項目はハッシュキーになるため)。
use Win32::OLE;
use Win32::OLE::Variant; # これがないと日付型系データが上手く取得できない
use Win32::OLE::Const 'Microsoft ActiveX Data Objects 2.0 Library';# adUseClient等が宣言されている
Win32::OLE->Option(Warn => 3); # エラー時にエラーメッセージを出力後、本プロセスが終了する
# 以下の接続情報を初期コーディングする。
my $server='';  # DBServer
my $db='';      # DBName
my $id='';      # ID
my $ps='';      # Password

    my ($Sql) = @_; # 引数取得(SQL文のみ)

    # DB接続
    my $objDB=Win32::OLE->new("ADODB.Connection");
    my $connStr="Provider=sqloledb;".
                "Data Source=$server;".
                "Initial Catalog=$db;".
                "User ID=$id;".
                "Password=$ps;"; #(WINDOWS認証の時は『Integrated Security=SSPI;』を付加する)
    $objDB->Open($connStr);
    if ($objDB->{Errors}->{Count}) {
        die "cannot connect '$connStr'";
    }

    # Recordsetを作成
    my $rs=Win32::OLE->new("ADODB.Recordset");

    # RecordCountを返すようにする
    $rs->{CursorLocation} = adUseClient; 

    # SQL文からハッシュキーにするための選択項目を配列に取得する。
    $Sql =~ /SELECT(.*?)FROM/i;     # ?の最小マッチにするのは、Where文にFROMが入る可能性があるため
    my $wk = $1;

    1 while $wk =~ s/\([^()]*\)//g; # 関数系を弾く
    $wk = ',' . $wk;                # 先頭に「,」を付加する
    $wk =~ s/,[^,]*? AS/,/gi;       # AS系を弾く
    $wk =~ s/^,//;                  # 先頭の「,」を削除する
    $wk =~ s/ //g;                  # スペースをつめる

    my @selectItem = split(/,/, $wk);

    # SELECTしたデータを、行は配列へ列は選択項目がキーのハッシュへ格納する。
    my %data;
    my @AoA;
    my $ref;
    $rs->Open($Sql, $objDB);
    while(!$rs->EOF and $rs->{RecordCount}!=0){
        foreach my $scalar (@selectItem) {
             $data{$scalar} = $rs->{Fields}->{$scalar}->{Value};
        }
        $rs->MoveNext();
        $ref = { %data };
        push @AoA, $ref;
    }
    $rs->Close();

    # DB切断
    $objDB->Close();
    return @AoA;
}

留意点:本ルーチンによるSELECT文フォーマット制限

  • SELECTとFROMを必ず同一行に記述する。(SELECT aaa, bbb, ccc FROM……)
  • 選択項目でエイリアスがある時は必ずASキーワードを使用する(SELECT X.aaa AS xxx, ……)
  • 選択項目は、アスター「*」は不可(選択項目はハッシュキーになるため)。