konekto Inc with PHP , MySQL コネクト株式会社 技術情報コンテンツ


Old/Zend Server/IBMi

IBM i で DB2 を使う

この情報の対象は下記のバージョンです。

  • Zend Server for IBMi Ver 5.0.1 日本語版
  • Zend Server for IBMi Ver 5.1.0 日本語版
  • Zend Core for i5/OS Ver 2.0.1 日本語版
  • Zend Core for i5/OS Ver 2.0.1AJ 日本語版

弊社では、Linux および Windows 用の Zend Server を引き続きお取り扱いしております。

注意事項

  • i5/OS, System iもしくはAS/400をご利用のかた
    • IBM iという語句を適宜お読み替え下さい。
  • Zend Core for i5/OSをご利用のかた
    • Zend Server for IBM iという語句を適宜お読み替え下さい。
  • db2関数のプログラムについて
    • ibm_db2 エクステンションのバージョンによっては、そのまま使用できない場合があります。
    • db2_pconnect関数の代わりに db2_connect関数を使用する場合は、
      各 exitの直前やプログラムの終了前に db2_close関数を記述してください。

その1 db2関数でデータ取得

YOURLIB ライブラリーの YOURPF 物理ファイルのデータを範囲指定して取得する例です。

/**
 * 接続オプション
 * SQL文でライブラリーを省略した場合の既定のライブラリーやライブラリーリストを指定できます。
 */
$options = array('i5_lib' => 'YOURLIB');
 
/**
 * DB2に接続します。
 * 引数の1番目はリレーショナルデータベース名です。DSPRDBDIREコマンドで確認できます。
 * PHPとDB2が同じIBMi環境に存在する場合は、*LOCAL や中身の無い文字列も使用できます。
 * 2番目と3番目はユーザーとパスワードです。
 * ユーザープロファイルによるコントロールが不要の場合は、下記の様に記述できます。
 */
$db_con = db2_pconnect('', '', '', $options);
if(!$db_con){
    echo '接続エラー:', db2_conn_errormsg();
    exit;
}
 
/**
 * SQLを準備します。
 * 物理ファイル YOURPF に得意先コード、得意先名、電話番号の3項目が存在し、得意先名が日本語と想定します。
 * 項目名はそれぞれ、TOKCOD, TOKNAM, TELNO で、TOKNAMの長さが20バイトと想定します。
 */
$query = ' SELECT TOKCOD, '
           /**
            * 値がUTF-8で帰ってくることを考慮して、SQLのCAST関数を用いて元の1.5倍以上の長さとして
            * 認識させる必要があるかもしれません。(半角カナの場合は3倍の長さになります)
            */
       . ' RTRIM(CAST(TOKNAM AS CHAR(30)) AS TOKNAM, '
           //文字列項目の場合、値の右端が半角や全角の空白で埋められています。SQLのRTRIM関数で除去できます。
       . ' RTRIM(TELNO) AS TELNO '
       . ' FROM YOURPF '
           /**
            * 得意先コードの範囲を?を使って指定できるようにしてみます。
            * ?をパラメーターマーカーといいます。
            */
       . ' WHERE TOKCOD BETWEEN ? AND ? ';
 
$stmt = db2_prepare($db_con, $query);
if(!$stmt){
    echo 'SQL準備エラー:', db2_stmt_errormsg();
    exit;
}
 
//それぞれのパラメーターマーカーに変数 $myMin と $myMax を割り当てます。
db2_bind_param($stmt, 1, "myMin", DB2_PARAM_IN, DB2_CHAR);
db2_bind_param($stmt, 2, "myMax", DB2_PARAM_IN, DB2_CHAR);
 
//得意先コードの範囲を指定します。
$myMin = 'A0000';
$myMax = 'Z9999';
 
//SQLを実行します。パラメーターマーカーの箇所に実際の値が当てはめられます。
$ret = db2_execute($stmt);
if(!$ret){
    echo 'SQL実行エラー:', db2_stmt_errormsg();
    exit;
}
 
//結果取り出しと表示
echo '<table border=1>',
     '<tr><th>得意先CD</th><th>得意先名</th><th>電話番号</th></tr>';
 
$row = array();
 
while($row = db2_fetch_array($stmt)) {
    echo '<tr>';
    foreach ($row as $col) {
        /**
         * 日本語項目のシフトイン及びシフトアウトの状態によっては、
         * さらにここで空白の除去が必要になるかもしれません。
         */
        echo '<td>', $col, '</td>';
    }
    echo '</tr>';
}
 
echo '</table><BR>';
 
/**
 * もし読み取り共用(*SHRRD)ロックによるトラブルで困った場合には、
 * SQL 実行結果のリソースを明示的に解放する手があります。
 */
//db2_free_result($stmt)

その2 db2関数でトランザクション

db2関数でトランザクションを用いる例です。COMMITやROLLBACKについてのFAQとあわせてご覧下さい。

//接続オプション
$options = array('autocommit' => DB2_AUTOCOMMIT_OFF,
                 'i5_commit'  => DB2_I5_TXN_READ_COMMITTED);
 
$db_con = db2_pconnect('', '', '', $options);
if(!$db_con){
    echo '接続エラー:', db2_conn_errormsg();
    exit;
}
 
//1項目だけ存在する物理ファイル YOURPF に、$myValue の値を追加します。
$query = ' INSERT INTO YOURLIB.YOURPF (FIELD1) VALUES(' . $myValue . ')';
 
$ret = db2_exec($db_con, $query);
if(!$ret){
    echo 'SQL実行エラー:', db2_stmt_errormsg();
    exit;
}
 
$ret = db2_commit($db_con);
if(!$ret){
    echo 'コミットエラー:', db2_stmt_errormsg();
    exit;
}
 
echo 'コミットしました';

その3 odbc関数

odbc関数は、おおよそ db2関数の先頭の db2_ を odbc_ に置き換える感覚で使用できます。
しかし異なる点もあります。下記にその例を記載します。

  • odbc_connect関数の第4引数には、db2_connect関数のような接続オプションは指定できません。
  • odbc_pconnectはありますが、odbc_pcloseはありません。(20110214時点)
  • エラーメッセージを取得する関数は2種類ではなく、odbc_errormsg関数のみです。
  • データを更新するためには、対象のオブジェクトに対してあらかじめ、 必ず ジャーナル処理を設定しておかなければいけません。
    トランザクションを使うかどうかとは 無関係 です。
  • db2_fetch_xxxx関数とodbc_fetch_xxxx関数の返り値の形式が同じとは限りません。
    var_dumpで差異を確認してプログラムを修正する必要があります。

その4 db2関数の応用例 PDF出力

PHPExcel というフリーのライブラリに内蔵されている TCPDF を使ってPDFを出力する例です。
2010年2月にPHPExcel Ver1.7.2を使って作成した資料を元にしています。

  • PHPExcelがinclude_path 上に存在すると想定します。
  • 名前、電話番号、住所、年齢の一覧を想定します。
require_once 'PHPExcel/Shared/PDF/config/lang/eng.php';
require_once 'PHPExcel/Shared/PDF/tcpdf.php';
 
/**
 * TCPDF インスタンス化
 * 引数1:用紙方向(L=横, P=縦)
 * 引数2:単位(mm, cm, pt=ポイント, in=インチ)
 * 引数3:用紙の大きさ(An, Bn...)
 */
$obj = new TCPDF('L', 'mm', 'A4');
 
/**
 * 日本語フォントを指定
 * 引数1:フォント名
 * 引数2:スタイル(空文字=標準, B=太字, I=斜体, U=下線付, D=取消線付)
 * 引数3:サイズ
 */
$obj->SetFont('arialunicid0-japanese', '', 10);
 
//書き出し対象のページを準備
$obj->AddPage();
 
/**
 * 一例として、下記のような配列で各列の幅、最初の行に書き出す項目名、寄せ方向(L=左, R=右)を設定
 */
$colStyles = array(
   array(20, '名前', 'L'),
   array(20, '電話', 'L'),
   array(40, '住所', 'L'),
   array( 6, '年齢', 'R'));
 
//最初の行に項目名を出力
foreach ($colStyles as $colStyle) {
   /**
    * 引数1:幅
    * 引数2:高さ
    * 引数3:出力値
    * 引数4:1=枠で囲む, 0=枠無し, T/B/L/R=上下左右の個別指定(組合せ可能)
    * 引数5:出力後の移動方向(0=右(アラビア語などは左)、1=次行、2=下)
    * 引数6:寄せ方向(C=中央, Lまたは空文字=左, R=右, J=両端)
    */
   $obj->Cell($colStyle[0], 6, $colStyle[1], 1, 0, 'C');
}
 
//改行
$obj->Ln();
 
$row = array();
 
//db2に接続し、プレペアされたSQLを実行したと想定します。
while($row = db2_fetch_array($stmt)) {
    foreach ($row as $colNum => $cell) {
        $obj->Cell($colStyles[$colNum][0], 6, $cell, 1, 0, $colStyles[$colNum][2]);
    }
 
    //改行
    $obj->Ln();
}
 
/**
 * 引数1:ファイル名
 * 引数2:出力先(I=ブラウザ, D=ダウンロード, F=ファイル保存, S=文字列として出力)
 */
$out = $obj->Output("friends.pdf", "I");
 
/**
 * 出力先=Sの場合の確認に利用
 *
 * var_dump($out);
 */

その5 db2関数の応用例 Excel出力

PHPExcel というフリーのライブラリを使ってExcelを出力する例です。
2010年2月にPHPExcel Ver1.7.2を使って作成した資料を元にしています。

  • PHPExcelがinclude_path 上に存在すると想定します。
  • 名前、電話番号、住所、年齢の一覧を想定します。
//PHPExcel インスタンス化
require_once 'PHPExcel.php';
require_once 'PHPExcel/IOFactory.php';
$obj = new PHPExcel();
 
//書き出し対象のシートおよびタイトルを準備
$obj->setActiveSheetIndex(0);
$sheet = $obj->getActiveSheet();
$sheet->setTitle('友人一覧');
 
/**
 * 一例として、下記のような配列で各列の幅、最初の行に書き出す項目名、データ型(文字型、数値型)を設定
 */
$colStyles = array(
   array(20, '名前', PHPExcel_Cell_DataType::TYPE_STRING ),
   array(20, '電話', PHPExcel_Cell_DataType::TYPE_STRING ),
   array(40, '住所', PHPExcel_Cell_DataType::TYPE_STRING ),
   array( 6, '年齢', PHPExcel_Cell_DataType::TYPE_NUMERIC));
 
//列番号の最大 列番号は 0, 1, 2, 3...
$colNumMax = count($colStyles) - 1;
 
//行番号は 1, 2, 3, 4, 5....
$rowNum = 1;
 
//最初の行に項目名を出力
foreach ($colStyles as $colNum => $colStyle) {
 
   //各列の幅を設定
   $sheet->getColumnDimensionByColumn($colNum)->setWidth($colStyle[0]);
 
   //項目名を書き出し
   $sheet->setCellValueByColumnAndRow($colNum, $rowNum, $colStyle[1]);
 
   //書式設定準備
   $cellStyle = $sheet->getStyleByColumnAndRow($colNum, $rowNum);
 
   //各セルは上下・左右ともに中央寄せ
   $cellStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
   $cellStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER);
 
   //各セルの上下に太線設定
   $cellBorder = $cellStyle->getBorders();
   $cellBorder->getTop()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
   $cellBorder->getBottom()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
 
   //左端のみ太線
   if ($colNum === 0) {
       $cellBorder->getLeft()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
   }
 
   //各セルの右に線を設定
   if ($colNum < $colNumMax) {
       $cellBorder->getRight()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
   } else {
       $cellBorder->getRight()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
   }
 
   //文字色
   $cellStyle->getFont()->getColor()->setARGB(PHPExcel_Style_Color::COLOR_DARKRED);
 
   //背景の色と塗りつぶし
   $cellStyle->getFill()->getStartColor()->setARGB(PHPExcel_Style_Color::COLOR_YELLOW);
   $cellStyle->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
}
 
//2行目以降にデータ一覧部分を書き出し
$rowNum++;
$row = array();
 
//db2に接続し、プレペアされたSQLを実行したと想定します。
while($row = db2_fetch_array($stmt)) {
   //各行ごとにデータ書き出し
   foreach ($row as $colNum => $cell) {
       $sheet->setCellValueExplicitByColumnAndRow($colNum, $rowNum, $cell, $colStyles[$colNum][2]);
 
       //書式設定準備
       $cellStyle  = $sheet->getStyleByColumnAndRow($colNum, $rowNum);
 
       //各セルの下に細線設定
       $cellBorder = $cellStyle->getBorders();
       $cellBorder->getBottom()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
 
       //左端のみ太線
       if ($colNum === 0) {
           $cellBorder->getLeft()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
       }
 
       //各セルの右に線を設定
       if ($colNum < $colNumMax) {
           $cellBorder->getRight()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
       } else {
           $cellBorder->getRight()->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
       }
   }
 
   $rowNum++;
}
 
//下端だけを太線化
//すでにテーブルの一番最後の行よりも下の行を指しているので一行戻ります。
$rowNum--;
for($colNum = 0; $colNum <= $colNumMax; $colNum++){
   $sheet->getStyleByColumnAndRow($colNum, $rowNum)->getBorders()->getBottom()
   ->setBorderStyle(PHPExcel_Style_Border::BORDER_THICK);
}
 
//Excel2007 用にファイル書き出し
$objWriter = PHPExcel_IOFactory::createWriter($obj, 'Excel2007');
$objWriter->save('friends.xlsx');
 
//Excel2003 以前用にファイル書き出し
//$objWriter = PHPExcel_IOFactory::createWriter($obj, 'Excel5');
//$objWriter->save('friends.xls');
 
//PDFとして書き出し (内蔵のTCPDFが利用される。ただし罫線がNG)
//$objWriter = PHPExcel_IOFactory::createWriter($obj, 'PDF');
//$objWriter->save('friends2.pdf');
 
//これで終わりです

最終更新のRSS