[4] PostgreSQLを使ってみよう (2000/11/12)

はじめに

 前回、「我が家のPCは一台増えて3台となった」と書きましたら、早速友人から「ずいぶん景気がいいじゃないか」というメールが来ました。しかし、そんなことはありません。なにしろ、もう6年以上前にショップブランドのDOS/Vマシンを買って以来、出来上がったPCを買ったことは一度もないのです。

 現在メインで使っているマシンは、主だったところがCeleron533A+BXマザー+192MBメモリ+Rage128Proというパーツ構成で、まあそこそこといった感じの性能です。サブマシンは、Celeron300A+BXマザー+64MBメモリ+RivaTNTで、もう完全に古臭い仕様と言ってもいいものです。さらに、LinuxのインストールされているマシンはMMXPentium200MHz+TXマザー+64MBメモリ+Millenium2という、なんというか化石のような構成になっています。

 これらのマシンは、それぞれメインマシンをグレードアップしていくたびに、お蔵入りとなっていく余ったパーツを寄せ集めて、ケースを調達しては組み上げてきたものです。その上、足りないものは弟から貰ったりもしていますから、無駄にお金を使ったりは全然していないのです。ケチケチPC道一直線で来たわけですね。

PostODBCをセットアップする

 さて、本題に入りましょう。Windows2000が動いているメインマシンとTCP/IPで接続されているLinuxマシン上でPostgreSQLが稼動している状態になっています。このPostgreSQLをWindowsから利用するための方法はいくつかありますが、一番手軽に使えそうなODBCによる接続をまず試してみたいと思います。

 PostgreSQL用のODBCドライバは日本PostgreSQLユーザー会のHPの、PostgreSQL用インターフェースのページからリンクされているPostgreSQL ODBC Driver日本語版のページからダウンロードできます。最新版は2000/06/17版です。このバージョンからPostgreSQL-7.0に対応しています。

 インストールの仕方は少々変わっていて、英語版のドライバーをインストールした後で、日本語版のDLLをWindowsのシステムディレクトリ(System又はSystem32)に上書きするというものです。私の場合はすでに以前のバージョンがインストールしてあったので、新しいpsqlodbc.dllを上書きしました。

 Windows2000なので、コントロールパネルの管理ツールにあるデータソース(ODBC)を開いてODBCデータソースアドミニストレータから、ドライバの設定をすることになります。追加ボタンを押してPostgreSQLを選択し、完了ボタンをおすとドライバの設定ダイアログが開きます。データソース名、データベース名、サーバーのIPアドレス又はコンピューター名、ユーザー名、パスワードを設定します。ポートはデフォルトのままPostgreSQLをインストールしてあるので、5432でOKです。気をつけないといけないのは、Options(Advanced)と表示されている、ドライバーとデータソースの設定ダイアログで、それぞれReadOnlyのチェックをオフにしてあげないと、データベースの更新が出来ないことです。デフォルトでは、ReadOnlyに設定されているようなので、これを外しておきます。

テストデータベースを作成する

 次に、まだ接続する先のPostgreSQLにデータベースを作成していませんから、これを作成することにします。Linuxマシンにユーザーpostgresで接続して、psqlを起動します。今回は郵便番号辞書を使って実験してみようと思うので、yubinというデータベースを作成することにします。

$ psql
Welcome to psql, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help on internal slash commands
       \g or terminate with semicolon to execute query
       \q to quit

postgres=# create database yubin;
CREATE DATABASE

 これで、yubinというデータベースが作成されました。\lで確認してみましょう。

postgres=# \l
        List of databases
  Database  |  Owner   | Encoding
------------+----------+----------
 postgres   | postgres | EUC_JP
 regression | postgres | EUC_JP
 template1  | postgres | EUC_JP
 yubin      | postgres | EUC_JP
(4 rows)

 確かに、作成されています。regressionテストを行ったので、regressionというデータベースが作成されていることも確認できます。4つのデータベースがあるわけですが、このうちtemplate1はinitdbで作成されるシステムデータベースですから、あまり触ったりしない方がよさそうです。postgresは現在のユーザーであるpostgresのユーザーデータベースで、他のユーザーをpostgresに追加した場合も、ユーザー名のデータベースがそのユーザーのデフォルトのデータベースとして作成されます。現在どのデータベースに接続しているかは、psqlのプロンプトに表示されています。

 データベースyubinに接続するには、\cコマンドを使用します。

postgres=# \c yubin
You are now connected to database yubin.
yubin=#

 続いて、テーブルt_yubinを作成します。

yubin=# create table t_yubin(id integer,zip varchar(8),address varchar(40),primary key(id));
NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index 't_yubin_pkey' for table 't_yubin'
CREATE
yubin=#

 フィールドzipとaddressに、indexを付けておいたほうがいいでしょうから、追加しておきましょう。

yubin=# create index zip_idx on t_yubin(zip);
CREATE
yubin=# create index address_idx on t_yubin(address);
CREATE

 さて、ここまで出来たらデータを追加してみましょう。データの追加にはAccess2000を利用しました。WindowsのIME用の郵便番号辞書から抽出した郵便番号のデータがあるので、これをAccessの「外部データの取り込み」−「インポート」を使用してテーブルにデータとして取り込みます。余計なフィールドをインポートしないようにスキップして、取り込んだデータから先頭部分のコメントを削除、主キー用にオートナンバー型のフィールドを追加してPostgreSQLと同じフィールド構成にします。インポートが終了したらテーブル名をt_yubinにしておきます。

 次にODBCデータソースの設定をしておきます。DSN名をPostgreSQL_Yubinにして、yubinデータベースに接続できるように設定します。これを、Accessから「外部データの取り込み」−「テーブルのリンク」を使用して、リンクテーブルとしてt_yubin_pgsqlを作成します。

 ここまでできたら、更新クエリーを使ってAccessからPostgreSQLにデータを挿入してしまいます。Accessの更新クエリーの使い方は横に置いておいて、SQLで次のように書いて実行します。

INSERT INTO t_yubin_pgsql
SELECT *
FROM t_yubin;

 実行している間に結構時間がかかるので、psqlで次のようなSQLを実行すると、まだ行がないといわれます。

yubin=# select count(*) from t_yubin;
 count
-------
     0
(1 row)

 1行づつインサートされているのではなく、テーブル丸ごとがトランザクションになっていることがこのことから伺えます。Accessの処理が終わった後では以下のように表示されます。

yubin=# select count(*) from t_yubin;
 count
--------
 126616
(1 row)

 実に126,616個のデータがあることがわかります。これくらいあれば、テストデータとしては十分です。

SQLで遊んでみる。

 それでは、いくつかデータを抽出してみましょう。全国に永田町という地名がどれだけあるか調べてみます。

yubin=# select * from t_yubin where address like '%永田町%';
   id   |   zip    |           address
--------+----------+------------------------------
  15022 | 100-0014 | 東京都千代田区永田町
  28337 | 329-2727 | 栃木県那須郡西那須野町永田町
  31176 | 368-0013 | 埼玉県秩父市永田町
  36757 | 417-0055 | 静岡県富士市永田町
  46256 | 500-8808 | 岐阜県岐阜市永田町
 101942 | 894-0023 | 鹿児島県名瀬市永田町
 112164 | 940-0873 | 新潟県長岡市永田町
(7 rows)

 郵便番号から住所を検索してみます。郵便番号の前3桁が777である住所は何ヶ所あるか調べてみます。

yubin=# select count(*) from t_yubin where zip like '777%';
 count
-------
    46
(1 row)

 結構ありますね。では、後の4桁が7777の所は、あるでしょうか?

yubin=# select count(*) from t_yubin where zip like '____7777';
 count
-------
    1
(1 row)

yubin=# select * from t_yubin where zip like '____7777';
   id   |   zip    |     address
--------+----------+------------------
 126524 | 999-7777 | 山形県酒田市丸沼
(1 row)

 これは一ヶ所だけですね。

PHP3で郵便番号検索システムを作ってみる。

 さて、ではこのデータベースを利用してApache+PHP3で郵便番号検索システムを作ってみます。この手のシステムはあちこちで紹介されていて、日本PostgreSQLユーザー会のHPからもリンクが張られています。とはいえ、あまり難しく考える必要もないので、郵便番号から住所を検索する、または住所の一部(全部)から郵便番号を検索するという機能を作ってみます。Apache+PHPはすでにセットアップされていることを前提として話を進めます。

 まず、PHP3でPostgreSQLに接続してみます。次のような内容のHTMLファイルを作成して、yubin1.php3という名前をつけてApacheのドキュメントルート(私の場合は/home/httpd/htmlです)に保存します。

<HTML>
<HEAD>
</HEAD>
<BODY>
<script language="php"> 
        $cn = pg_connect("localhost","5432","","","yubin");
        
        echo ("PostgreSQL接続ID = " . $cn);
        echo ("<BR>");
        
        $result = pg_exec($cn,"SELECT * From t_yubin;");
        
        echo ("データの総数は");
		echo (pg_numrows($result));
		echo ("件です<BR>");
        
        pg_close($cn);
    </script>
</BODY>
</HTML>

 WWWブラウザからアクセスすると以下のような結果が返ってきます。

PostgreSQL接続ID = 1
データの総数は126616件です

 ちゃんと接続できてますね。では、郵便番号をテキストボックスに入力して、検索ボタンを押すと地名が表示されるようにしてみましょう。

<HTML>
<HEAD>
</HEAD>
<BODY>
<script language="php"> 
        $cn = pg_connect("localhost","5432","","","yubin");
        
        if ($cn > 0) {
        	echo ("データベースへの接続OK<BR>");
        	} else {
        	echo ("データベースに接続できません<BR>");
        	pg_close($cn);
        	exit;
        	}
    </script>

<HR>
<FORM ACTION="yubin2.php3" METHOD="POST">
	郵便番号を入力して検索ボタンを押してください。<BR>
	<INPUT TYPE="text" NAME="zipcode" SIZE="20"><BR>
	<INPUT TYPE="submit" NAME="button" VALUE="検索開始"><BR>
</FORM>

<script language="php">
		if ($button!="") {		//初回及び検索対象なし以外
			$usersql = "SELECT * FROM t_yubin where zip like '%" . $zipcode . "%'";
			//echo $usersql;
			$result = pg_exec($cn,$usersql);
			$rows=pg_numrows($result);
			$cols = pg_numfields($result);
			
			echo ($rows);
			echo ("件が見つかりました。");
			echo ("<HR>");
			
			print("<TABLE BORDER>\n");
			
			for ($j = 0;$j < $rows;$j++) {
				if ($j == 0) {
					print("<TR>");
					for ($i = 0;$i < $cols;$i++) {
					$str = pg_fieldname($result,$i);
					print("<TH>$str</TH>");
					}
				print("</TR>\n");
				}

				print("<TR>");

				for ($i = 0;$i < $cols;$i++) {
					$str = pg_result($result,$j,$i);	// データの取り出し
					print("<TD>$str</TD>");
					}

				print("</TR>\n");

				}
			print("</TABLE>\n");
			}
		pg_freeresult($result);	// 検索結果の解放
		pg_close($cn);
	</script>
</BODY>
</HTML>

 実行した結果はこんな感じです。

<初期表示>

<郵便番号入力>

<検索結果>

 次回は、PHP3のインストールにまつわる苦労についての予定です。

To Be Continued