データベース(ODBC)との接続 |
httpd/Fasttrack/Enterprise/IIS/PWS |
Access97をすでにインストールしてあり、Access97インストール時等に32ビットODBCドライバもすでにインストールしてあることを前提にします。ODBCドライバはAccess97等に付属していますが、手元にない場合はMicrosoftのサイトから得られます。
http://www.microsoft.com/support/products/backoffice/odbc/
PerlモジュールWin32::ODBCを入手しインストールします。
ActiveState社 ActivePerl build 507 では標準でインストールされています。
もし、古いバージョンを使っていたりしてインストールされていない場合は次のサイトから入手します。
インストール方法はパッケージに付属のReadme等を参照してください。
ActiveState Perl for Win32 の場合は ppm でインストールできます。
例として次の内容で設定を行います。
データベース名: Address.mdb
データソース名: 住所録
テーブル名: 住所テーブル
テーブル項目:
住所録ID | 氏名 | シメイ | 配偶者名 | 住所1 | 都道府県 | 郵便番号 | 国名 | 電子メールアドレス | 自宅TEL | 会社直通TEL | 会社内線番号 | FAX番号 | 生年月日 | 年賀状の送付 | 備考 |
Access97でデータベースを作成します。ここでは、Access97でテンプレートデータベースから住所録を作成しています。
ODBCデータソース アドミニストレータでDSN(データソース名)を設定します。
スタート->設定->コントロールパネルを選び32ビットODBCをダブルクリックします。
システムDSNを選び、「追加」をクリックします。
データソースドライバとしてMicrosoft Access Driverを選び、「完了」をクリックします。
データソース名に適当な名前を入力します。ここでは、「住所録」とします。
次に既存のデータベースを選択します。選択ボタンをクリックしてAccessで作成したデータベースを選びます。選んだら「OK」ボタンをクリックします。
”ODBC Microsoft Access97 セットアップ”画面で「OK」をクリックするとシステムデータソースとして設定されます。
テストを行います。
コマンドモニタで test.pl でテストしてみます。test.pl はWin32::ODBCパッケージの中に含まれています。
perl test.pl test.pl |
正常にインストールされている場合は、モニタ上にデータが表示され、エラーがないことが表示されます。
このサンプルスクリプトはテーブルのリレーションには対応していません。
検索画面等が表示されるまでは少し時間がかかるかもしれません。
#!/usr/bin/perl # # odbc.cgi # # (C)1999 Kaoru Fujita # # データの[変更]はカラム属性のためか Access97 のテンプレート # 住所録ではエラーとなるので無効としてある。 # use lib './lib'; require 'jcode.pl'; require 'util.pl'; use Win32::ODBC; # # 定数 # # タイトル $Title = 'データベース接続サンプル プログラム'; # CGI の仮想パス $CGIPath = '/cgi-bin'; # プログラム名 use File::Basename; $Program = basename($0); # 漢字コード $CharSet = 'Shift_JIS'; $Encoding = 'sjis'; # # メインプログラム # parseInput($Encoding); initProc(); # テスト用 #$in{'Action'} = 'getData'; #$in{'DSN'} = 'test01'; $date = &getDate(); $act = $in{'Action'}; if ($act eq 'getData') { viewData(); } elsif ($act eq 'getField') { viewField(); } elsif ($act eq 'getQueryField') { viewQueryField(); } elsif ($act eq 'modifyData') { modifyData(); } elsif ($act eq 'addData') { addData(); } elsif ($act eq 'deleteData') { deleteData(); } else { viewData(); } exit(0); # # <IN> なし # <OUT> 日時(String) # sub getDate { ($sec, $min, $hour, $mday, $mon, $year) = localtime(time); $year += 1900; return "$year/$mon/$mday $hour:$min:$sec"; } # # <IN> # <OUT> # sub initProc { print "Content-type: text/html\n\n"; } # # <IN> なし # <OUT> なし # sub viewData { my(@table, $table); my($dsn) = $in{'DSN'}; # ODBC オブジェクトの生成 if (!($O = new Win32::ODBC($dsn))) { exitError('ODBCオブジェクトが生成できません(DSN='.$dsn.")\n". Win32::ODBC::Error()); } # ODBC コネクションのオープン $O->Connection(); # テーブル名の取得 foreach ($O->TableList("", "", "%", "TABLE, VIEW, SYSTEM_TABLE")){ push(@table, $_); if ($in{'TableName'} eq $_) { $table = $_; break; } } if (!$table) { exitError("テーブルがありません: $in{'TableName'} [@table]"); } # 列の最大値は? #$iTemp = $O->GetStmtOption($O->SQL_MAX_ROWS); # SQL の発行 my($sql) = "SELECT * FROM [$table]"; if ($O->Sql("$sql")) { exitError('Sql()が失敗しました: '.$O->Error()."\n".$sql); $O->Close(); } @FieldNames = $O->FieldNames(); my($cond); for ($i=0; $i < scalar(@FieldNames); $i++) { my($fn) = $FieldNames[$i]; next if (!$in{$fn}); next if ($in{$fn} eq ''); $cond .= " And " if ($cond); if ($i == 0) { $cond .= "$fn = $in{$fn}"; } else { $cond .= "$fn = \'$in{$fn}\'"; } } $sql = "SELECT * FROM [$table]"; if ($cond) { $sql .= " WHERE " . $cond; } if ($O->Sql($sql)) { exitError('Sql()が失敗しました: '.$O->Error()."\n".$sql); $O->Close(); } print <<END_OF_HTML_1; <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> <SCRIPT language="JavaScript"> <!-- function selectID(form) { END_OF_HTML_1 for ($i=0; $i < scalar(@FieldNames); $i++) { print "\t". 'top.Lower.document.forms[0].elements['.$i.'].value = '. 'form.elements['.$i.'].value;'."\n"; } print <<END_OF_HTML_2; } //--> </SCRIPT> </HEAD> <BODY> <!--FORM name="Data"--> <TABLE> END_OF_HTML_2 print "<TR>\n"; for ($i=0; $i < scalar(@FieldNames); $i++) { my($fn) = $FieldNames[$i]; print '<TH valign="left" nowrap>'.$fn."</TH>\n"; push(@hidden, '<INPUT type="hidden" name="'.$fn.'" value="'.$in{$fn}.'">'."\n"); } print "</TR>\n"; # 行レコードの取得 while($O->FetchRow()){ undef %Data; %Data = $O->DataHash(); print "<FORM>\n"; print "<TR>\n"; for ($i=0; $i < scalar(@FieldNames); $i++) { $d = $Data{$FieldNames[$i]}; $d = ($i==0) ? '<INPUT type="button" name="Col-'.$i.'" value="'.$d.'" onClick="selectID(this.form)">' : '<INPUT type="hidden" name="Col-'.$i.'" value="'.$Data{$FieldNames[$i]}.'">'.$d; print '<TD NOWRAP BGCOLOR="#D0D0D0">'.$d."</TD>\n"; } print "</TR>\n"; print "</FORM>\n"; } print "</TABLE>\n"; print "<FORM action=\"$CGIPath/$Program\" name=\"Update\">\n"; print @hidden; print '<INPUT type="hidden" name="Action" value="getData">'."\n"; print '<INPUT type="hidden" name="DSN" value="'.$dsn.'">'."\n"; print '<INPUT type="hidden" name="TableName" value="'.$table.'">'."\n"; print "</FORM>\n"; print "</BODY>\n"; print "</HTML>\n"; # ODBC コネクションのクローズ $O->Close(); } # # <IN> なし # <OUT> なし # sub viewField { my(@table, $table); my($dsn) = $in{'DSN'}; # ODBC オブジェクトの生成 if (!($O = new Win32::ODBC($dsn))) { exitError('ODBCオブジェクトが生成できません(DSN='.$dsn.")\n". Win32::ODBC::Error()); } # ODBC コネクションのオープン $O->Connection(); # テーブル名の取得 foreach ($O->TableList("", "", "%", "TABLE, VIEW, SYSTEM_TABLE")){ push(@table, $_); if ($in{'TableName'} eq $_) { $table = $_; break; } } if (!$table) { exitError("テーブルがありません: $in{'TableName'} [@table]"); } # SQL の発行 if ($O->Sql("SELECT * FROM [$table]")) { exitError('Sql()が失敗しました: '.$O->Error()); } @FieldNames = $O->FieldNames(); print <<END_OF_HTML_1; <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> </HEAD> <BODY> <TABLE> END_OF_HTML_1 print "<TR>\n"; for ($i=0; $i < scalar(@FieldNames); $i++) { print '<TH valign="left" nowrap>'.$FieldNames[$i]."</TH>\n"; push(@hidden, '<INPUT type="hidden" name="'.$FieldNames[$i].'" value="">'."\n"); } print "</TR>\n"; print "</TABLE>\n"; print "<FORM action=\"$CGIPath/$Program\" name=\"Update\">\n"; print @hidden; print '<INPUT type="hidden" name="Action" value="getData">'."\n"; print '<INPUT type="hidden" name="DSN" value="'.$dsn.'">'."\n"; print '<INPUT type="hidden" name="TableName" value="'.$table.'">'."\n"; print "</FORM>\n"; print "</BODY>\n"; print "</HTML>\n"; # ODBC コネクションのクローズ $O->Close(); } # # <IN> なし # <OUT> なし # sub viewQueryField { my(@table, $talbe); my($dsn) = $in{'DSN'}; # ODBC オブジェクトの生成 if (!($O = new Win32::ODBC($dsn))) { exitError('ODBCオブジェクトが生成できません(DSN='.$dsn.")\n". Win32::ODBC::Error()); } # ODBC コネクションのオープン $O->Connection(); # テーブル名の取得 foreach ($O->TableList("", "", "%", "TABLE, VIEW, SYSTEM_TABLE")){ push(@table, $_); if ($in{'TableName'} eq $_) { $table = $_; break; } } if (!$table) { exitError("テーブルがありません: $in{'TableName'} [@table]"); } # SQL の発行 if ($O->Sql("SELECT * FROM [$table]")) { exitError('Sql()が失敗しました: '.$O->Error()); } @FieldNames = $O->FieldNames(); print <<END_OF_HTML_1; <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> <SCRIPT language="JavaScript"> <!-- function sendData(act) { document.Field.Action.value = act; document.Field.submit(); } function searchData() { for (i in document.Field.elements) { n = document.Field.elements[i].name; v = document.Field.elements[i].value; for (j in top.Upper.document.Update.elements) { if (top.Upper.document.Update.elements[j].name == n) { top.Upper.document.Update.elements[j].value = v; break; } } } top.Upper.document.Update.submit(); } //--> </SCRIPT> </HEAD> <BODY> END_OF_HTML_1 print "<FORM name=\"Field\" action=\"$CGIPath/$Program\">\n"; print "<TABLE>\n"; for ($i=0; $i < scalar(@FieldNames); $i++) { print "<TR>\n"; print '<TD>'.$FieldNames[$i]."</TD>\n"; print '<TD><INPUT type="textarea" name="'.$FieldNames[$i].'" size="36"></TD>'."\n"; print "</TR>\n"; } print "</TABLE>\n"; print '<INPUT type="hidden" name="Action" value="">'."\n"; print '<INPUT type="hidden" name="DSN" value="'.$dsn.'">'."\n"; print '<INPUT type="hidden" name="TableName" value="'.$table.'">'."\n"; print '<INPUT type="button" name="Search" value="検索" onClick="searchData()">'."\n"; # print '<INPUT type="button" name="Modify" value="変更" onClick="sendData(\'modifyData\')">'."\n"; print '<INPUT type="button" name="Add" value="新規登録" onClick="sendData(\'addData\')">'."\n"; print '<INPUT type="button" name="Delete" value="削除" onClick="sendData(\'deleteData\')">'."\n"; print '<INPUT type="reset" name="Clear" value="クリア">'."\n"; print "</FORM>\n"; print "</BODY>\n"; print "</HTML>\n"; # ODBC コネクションのクローズ $O->Close(); } # # <IN> なし # <OUT> なし # sub modifyData { my(@table, $talbe); my($dsn) = $in{'DSN'}; # ODBC オブジェクトの生成 if (!($O = new Win32::ODBC($dsn))) { exitError('ODBCオブジェクトが生成できません(DSN='.$dsn.")\n". Win32::ODBC::Error()); } # ODBC コネクションのオープン $O->Connection(); # テーブル名の取得 foreach ($O->TableList("", "", "%", "TABLE, VIEW, SYSTEM_TABLE")){ push(@table, $_); if ($in{'TableName'} eq $_) { $table = $_; break; } } if (!$table) { exitError("テーブルがありません: $in{'TableName'} [@table]"); } # SQL の発行 if ($O->Sql("SELECT * FROM [$table]")) { exitError('Sql()が失敗しました: '.$O->Error(). "\n"."SELECT * FROM [$table]"); } @FieldNames = $O->FieldNames(); $firstf = $FieldNames[0]; # 'ID' field for ($i=1; $i < scalar(@FieldNames); $i++) { $set = $set."$FieldNames[$i] = \'$in{$FieldNames[$i]}\',"; } chop($set); if ($O->Sql("UPDATE $table SET $set WHERE ID = $in{$firstf}")) { exitError('Sql()が失敗しました: '.$O->Error(). "\n"."UPDATE $table SET $set WHERE ID = $in{$firstf}"); } print <<END_OF_HTML_1; <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> <SCRIPT language="JavaScript"> <!-- function update() { top.Upper.document.Update.submit(); } function sendData(act) { document.Field.Action.value = act; document.Field.submit(); } //--> </SCRIPT> </HEAD> <BODY onLoad="update()"> END_OF_HTML_1 print "<FORM name=\"Field\" action=\"$CGIPath/$Program\">\n"; print "<TABLE>\n"; for ($i=0; $i < scalar(@FieldNames); $i++) { print "<TR>\n"; print '<TD>'.$FieldNames[$i]."</TD>\n"; print '<TD><INPUT type="textarea" name="'.$FieldNames[$i].'" size="36"></TD>'."\n"; print "</TR>\n"; } print "</TABLE>\n"; print '<INPUT type="hidden" name="Action" value="">'."\n"; print '<INPUT type="hidden" name="DSN" value="'.$dsn.'">'."\n"; print '<INPUT type="hidden" name="TableName" value="'.$table.'">'."\n"; print '<INPUT type="button" name="Search" value="検索" onClick="searchData()">'."\n"; # print '<INPUT type="button" name="Modify" value="変更" onClick="sendData(\'modifyData\')">'."\n"; print '<INPUT type="button" name="Add" value="新規登録" onClick="sendData(\'addData\')">'."\n"; print '<INPUT type="button" name="Delete" value="削除" onClick="sendData(\'deleteData\')">'."\n"; print '<INPUT type="reset" name="Clear" value="クリア">'."\n"; print "</FORM>\n"; print "</BODY>\n"; print "</HTML>\n"; # ODBC コネクションのクローズ $O->Close(); } # # <IN> なし # <OUT> なし # sub addData { my(@table, $table); my($dsn) = $in{'DSN'}; # ODBC オブジェクトの生成 if (!($O = new Win32::ODBC($dsn))) { exitError('ODBCオブジェクトが生成できません(DSN='.$dsn.")\n". Win32::ODBC::Error()); } # ODBC コネクションのオープン $O->Connection(); # テーブル名の取得 foreach ($O->TableList("", "", "%", "TABLE, VIEW, SYSTEM_TABLE")){ push(@table, $_); if ($in{'TableName'} eq $_) { $table = $_; break; } } if (!$table) { exitError("テーブルがありません: $in{'TableName'} [@table]"); } # SQL の発行 if ($O->Sql("SELECT * FROM [$table]")) { exitError('Sql()が失敗しました: '.$O->Error()); } @FieldNames = $O->FieldNames(); # ID の最大値を求める my($sql) = "SELECT MAX\($FieldNames[0]\) FROM [$table]"; if ($O->Sql($sql)) { exitError('Sql()が失敗しました: '.$O->Error()."\n"."$sql"); } # SQL の発行 $O->FetchRow(); $in{$FieldNames[0]} = $O->Data() + 1; for ($i=0; $i < scalar(@FieldNames); $i++) { $values = $values."\'$in{$FieldNames[$i]}\',"; } chop($values); if ($O->Sql("INSERT INTO $table VALUES($values)")) { exitError('Sql()が失敗しました: '.$O->Error(). "\nINSERT INTO $table VALUES($values)"); } print <<END_OF_HTML_1; <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> <SCRIPT language="JavaScript"> <!-- function update() { top.Upper.document.Update.submit(); } function sendData(act) { document.Field.Action.value = act; document.Field.submit(); } //--> </SCRIPT> </HEAD> <BODY onLoad="update()"> END_OF_HTML_1 print "<FORM name=\"Field\" action=\"$CGIPath/$Program\">\n"; print "<TABLE>\n"; for ($i=0; $i < scalar(@FieldNames); $i++) { print "<TR>\n"; print '<TD>'.$FieldNames[$i]."</TD>\n"; print '<TD><INPUT type="textarea" name="'.$FieldNames[$i].'" size="36"></TD>'."\n"; print "</TR>\n"; } print "</TABLE>\n"; print '<INPUT type="hidden" name="Action" value="">'."\n"; print '<INPUT type="hidden" name="DSN" value="'.$dsn.'">'."\n"; print '<INPUT type="hidden" name="TableName" value="'.$table.'">'."\n"; print '<INPUT type="button" name="Search" value="検索" onClick="searchData()">'."\n"; # print '<INPUT type="button" name="Modify" value="変更" onClick="sendData(\'modifyData\')">'."\n"; print '<INPUT type="button" name="Add" value="新規登録" onClick="sendData(\'addData\')">'."\n"; print '<INPUT type="button" name="Delete" value="削除" onClick="sendData(\'deleteData\')">'."\n"; print '<INPUT type="reset" name="Clear" value="クリア">'."\n"; print "</FORM>\n"; print "</BODY>\n"; print "</HTML>\n"; # ODBC コネクションのクローズ $O->Close(); } # # <IN> なし # <OUT> なし # sub deleteData { my(@table, $table); my($dsn) = $in{'DSN'}; # ODBC オブジェクトの生成 if (!($O = new Win32::ODBC($dsn))) { exitError('ODBCオブジェクトが生成できません(DSN='.$dsn.")\n". Win32::ODBC::Error()); } # ODBC コネクションのオープン $O->Connection(); # テーブル名の取得 foreach ($O->TableList("", "", "%", "TABLE, VIEW, SYSTEM_TABLE")){ push(@table, $_); if ($in{'TableName'} eq $_) { $table = $_; break; } } if (!$table) { exitError("テーブルがありません: $in{'TableName'} [@table]"); } # SQL の発行 if ($O->Sql("SELECT * FROM [$table]")) { exitError('Sql()が失敗しました: '.$O->Error()); } @FieldNames = $O->FieldNames(); # ID の最大値を求める $firstf = $FieldNames[0]; $sql = "DELETE * FROM [$table] WHERE $firstf = $in{$firstf}"; if ($O->Sql($sql)) { exitError('Sql()が失敗しました: '.$O->Error()."\n".$sql); } print <<END_OF_HTML_1; <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet"> <TITLE>$Title</TITLE> <SCRIPT language="JavaScript"> <!-- function update() { top.Upper.document.Update.submit(); } function sendData(act) { document.Field.Action.value = act; document.Field.submit(); } //--> </SCRIPT> </HEAD> <BODY onLoad="update()"> END_OF_HTML_1 print "<FORM name=\"Field\" action=\"$CGIPath/$Program\">\n"; print "<TABLE>\n"; for ($i=0; $i < scalar(@FieldNames); $i++) { print "<TR>\n"; print '<TD>'.$FieldNames[$i]."</TD>\n"; print '<TD><INPUT type="textarea" name="'.$FieldNames[$i].'" size="36"></TD>'."\n"; print "</TR>\n"; } print "</TABLE>\n"; print '<INPUT type="hidden" name="Action" value="">'."\n"; print '<INPUT type="hidden" name="DSN" value="'.$dsn.'">'."\n"; print '<INPUT type="hidden" name="TableName" value="'.$table.'">'."\n"; print '<INPUT type="button" name="Search" value="検索" onClick="searchData()">'."\n"; # print '<INPUT type="button" name="Modify" value="変更" onClick="sendData(\'modifyData\')">'."\n"; print '<INPUT type="button" name="Submit" value="新規登録" onClick="sendData(\'submitData\')">'."\n"; print '<INPUT type="button" name="Delete" value="削除" onClick="sendData(\'deleteData\')">'."\n"; print '<INPUT type="reset" name="Clear" value="クリア">'."\n"; print "</FORM>\n"; print "</BODY>\n"; print "</HTML>\n"; # ODBC コネクションのクローズ $O->Close(); } #--End of odbc.cgi |
Win32::ODBC のほかに、DBI::ODBC というものもあります。
http://www.hermetica.com/technologia/DBI/
DBIパッケージはいろいろなDBMSに接続できるモジュールがあります。
cgi-bin/odbc.cgi
cgi-bin/lib/util.pl
docs/Samples/odbc_access.html
docs/Samples/odbc_up.html
docs/Samples/odbc_low.html