インターネットを活用したプログラムを作成する場合、データを保存管理するためのデータベースと、データベースのデータを処理するためのプログラム言語が必要となってくる。今回の予備実験では、そのためにリレーショナルデータベースと、Webの動的なプログラム言語である PHP について説明する。
リレーショナル・データベース
データベースは、データを保存し、矛盾が発生しない様に管理してくれるシステムであり、インターネットで活用されている。
データを確実に保存し、矛盾なく扱うためには、本来複雑なプログラムが必要となる。この中で、データを表形式のテーブルを組み合わせて管理するシステムはリレーショナルデータベースと呼ばれる。リレーショナルデータベースでは、データの問い合わせなどの処理が簡単にできるように、SQL と呼ばれる言語を使って処理を行う。
大量のデータをインターネットの中で利用するためには、ネットワークを経由してデータの問い合わせが求められ、有名なデータベースシステムには、Oracle, MySQL などがある。今回の実験では、ネットワーク機能は持たないが簡単な手続きで使うことができる SQLite を使って説明する。
また、今回の予備実験では時間も限られることから、複数の表を組み合わせた SQL の処理については割愛する。
SQLの基本
リレーショナルデータベースでは、データの基本は表形式データであり、1つの表に相当するデータはテーブルと呼ぶ。
以下の様な名前・住所・年齢のデータがあったとすると、1人前のデータをレコードと呼び、name, addr, age といった属性はカラムと呼ぶ。
name | addr | age | |
t-saitoh | 越前市 | 55 | ←レコード |
sakamoto | 福井市 | 50 | |
murata | 福井市 | 35 | |
↑カラム |
データの型には、文字列型(char型,varchar型,text型)や、数値型(integer型,decimal型,real型)などがあり、create table 文にてカラムの型を定義する。
create table テーブルを作る
データベースの表を使う最初には、create table 文を実行する。C言語での struct 文をイメージすると解り易いかもしれないが、データはデータベースの中に永続的に保存されるので、システムを動かす最初に一度実行するだけで良い。
上記のような名前・住所・年齢のデータ構造であれば、次の様な create table 文を使う。
create table テーブル名 ( カラム名1 型1 , カラム名2 型2 ) ; -- 例 -- create table PERSON ( -- テーブル名:PERSON name varchar( 20 ) , -- 名前 addr varchar( 20 ) , -- 住所 age integer , -- 年齢 primary key( name ) -- name はデータ検索のキーであり重複は許されない ) ;
これと同じ様な処理をC言語で書くのであれば、以下の様な構造体宣言と同じであろう。
struct PERSON { char name[ 20 ] ; // 名前 char addr[ 20 ] ; // 住所 int age ; // 年齢 } ;
drop table テーブルを消す
データベースは永続的に保存されるので、テーブル全体のデータが不要であれば、drop table 命令で、テーブル全体を消す。
drop table テーブル名 ; -- 例 -- drop table PERSON ;
insert into レコードを追加
データベースに1レコードを保存するには、insert文を用いる。
insert into テーブル名 ( カラム名... ) values( 値... ) ; -- 例 -- insert into PERSON ( name , addr , age ) values ( 't-saitoh' , '越前市' , 55 ) ; insert into PERSON ( name , addr , age ) values ( 'sakamoto' , '福井市' , 50 ) ; insert into PERSON ( name , addr , age ) values ( 'murata' , '福井市' , 35 ) ;
delete レコードを消す
データベースのレコードを消すには、delete 文を用いる。条件を満たす複数のデータをまとめて消すことができる。
delete from テーブル名 where 条件 ; -- 例 -- -- 40歳未満のデータを全て消す。 murata,福井市,35 が消える。 delete from PERSON where age < 40 ;
update レコードを更新
データベースのレコードを修正するには、update 文を用いる。条件を満たす複数のデータをまとめて修正することもできる。
update テーブル名 set カラム = 値 where 条件 ; -- 例 -- -- 住所が越前市のレコードの年齢を 0 にする。 update PERSON set age = 0 where addr == '越前市' ;
select データを探す
データベースの内容を参照するための命令が select 文。where を記載することで、特定の条件のデータだけを選択したり、特定のカラムだけを抽出することができる。
select カラム名 from テーブル名 where 条件 ; -- 例 -- -- PERSON の全データを出力 select * from PERSON ; -- PERSON の住所が福井市だけを選別し、名前と住所を抽出 select name,addr from PERSON where addr = '福井市' ; -- PERSON の年齢の最高値を出力 (集約関数) select max(age) from PERSON where addr = '福井市' ; -- PERSON の年齢条件を満たす人数を数える (集約関数) select count(name) from PERSON where age >= 50 ;
動的なプログラム言語とPHP
本来、Webサーバが作られた頃は、論文や研究用のデータを公開する物であったが、扱うデータが増えるにつれ、特定の論文や研究データの一覧を表示したり探したりという処理が求められた。こういった処理のためにWebページのアクセスを受けた時に処理を実行する CGI という機能があったが、これを発展させてできたプログラム言語が PHP である。
PHPでは、ページを表示するための HTML の中に <?php … ?> のといった開始タグ・終了タグの中に、ブラウザから送られてきたデータに合わせて、処理を行うPHPの命令を記述し、データを(一般的にはHTML形式で)表示することができる。基本文法は C 言語に似ているが、様々なデータを扱うために変数にはどのような型でも保存できるようになっている。
ブラウザからデータを送るためのform文
ブラウザで入力欄を作ったり選択肢を表示し、その結果を送るための HTML は、入力フォーム(form)と呼ぶ。
<form method="get" action="処理ページ" > <input type="text" name="変数名" /> <input type="radio" name="変数名" value="値" /> <input type="checkbox" name="変数名" value="値" /> <textarea cols="横文字数" rows="行数"></textarea> <select name="変数名"> <option value="値1">表示1</option> <option value="値2">表示2</option> </select> <input type="submit" value="実行ボタンに表示する内容" /> </form>
formでは、入力する項目に変数名の名前を付け、action=”” で示したページにデータを送る。
PHPのプログラムの基本
PHPのプログラムは、外見は一般的に HTML ファイルであり、途中で <?php のタグからは、?> までの範囲が、PHP で処理が行われる。PHP のプログラムで print が実行されると、その場所に print 内容が書かれているような HTML ファイルが生成され、ブラウザで表示される。
PHP の中で変数は、$ で始まり、型宣言は基本的に不要である。
文字データを連結する場合は、“.” 演算子を使う。ダブルクオテーション”…”で囲まれた文字列の中の $名前 の部分は、変数名として扱われ、変数名の内容に置き換えられる。
HTMLのform文の action 属性で示された php であれば、PHPの中で送られてきた値を $_GET[‘変数名’] (method=”get”の場合)、 $_POST[‘変数名’] (method=”post”の場合)、または $_REQUEST[‘変数名’] (method=”get” or “post”) で参照できる。
((( sample.php ))) <html> <head> <title>sample.php</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <form action="sample.php" method="POST"> <input name="A" type="text" /> <!-- 変数 $A --> + <input name="B" type="text" /> <!-- 変数 $B --> = <?php ini_set( 'error_reporting' , E_WARNING ) ; if ( $_REQUEST[ "A" ] != "" && $_REQUEST[ "B" ] != "" ) { print $_REQUEST[ "A" ] + $_REQUEST[ "B" ] ; } else { print "<INPUT TYPE=submit>" ; } ?> </form> </body> </html>
PHPでデータベースを扱う
SQLのデータベースを、プログラム言語の中で扱う場合は、その記述も色々である。PHPでは以下の様にSQLを扱う。
((( survey-init.php ))) <html> <head> <title>survey_init.php</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php // デバッグ用にエラー警告を表示する ini_set( 'error_reporting' , E_WARNING ) ; // データベースに接続する $data_dir = "../public_data" ; $dbh = new PDO( "sqlite:$data_dir/sqlite.db" ) ; // データベースを初期化する $init_sql = "drop table if exists Survey ;" . "create table Survey (" . " uid varchar( 20 ) ," . " item varchar( 10 )" . ") ;" . "insert into Survey ( uid , item ) values ( 't-saitoh' , '猫' ) ;" . "insert into Survey ( uid , item ) values ( 'tomoko' , 'ケーキ' ) ;" . "insert into Survey ( uid , item ) values ( 'mitsuki' , 'ボードゲーム' ) ;" ; if ( $dbh->exec( $init_sql ) < 0 ) { print "Error: $init_sql" ; } // データベースの表形式を読み出し、表形式で出力する。 print "<table border='1'>\n" ; print "<tr><td align='center'>uid</td><td align='center'>item</td></tr>\n" ; $select_sql = "select uid,item from Survey ;" ; foreach( $dbh->query( $select_sql ) as list( $uid , $item ) ) { print "<tr><td>$uid</td><td>$item</td></tr>\n" ; } print "<table>\n" ; // データベースの単一データを取り出す $count_sql = "select count(item) from Survey where item = 'ケーキ' ;" ; print $dbh->query( $count_sql )->fetchColumn() ; ?> </body> </html>
PHPの主要なSQL関数(PDO)
$dbh = new PDO(…) ; データベースに接続するハンドラを取得。 $dbh->exec( “create…” ) ; データベースでSQLを実行。 $dbh->query( “select…” ) ; データベースに問い合わせ。「1レコードに対応した配列」が全データだけ繰り返す、2次元配列を返す。 $dbh->query( “…” )->fetchColumn() 結果が1つだけの問い合わせ。集約関数の結果を参照する場合に用いる。
練習問題(1)
- 上記の survey-init.php の select 文の部分を編集し、色々なデータ検索を試してみよ。
入力フォームのデータをデータベースに書き込む
((( survey-vote.php ))) <?php // エラー警告を表示 ini_set( 'error_reporting' , E_WARNING ) ; // form から送られてきた変数を保存 $uid = $_REQUEST[ "uid" ] ; $item = $_REQUEST[ "item" ] ; // データベースに接続する $data_dir = "../public_data" ; $dbh = new PDO( "sqlite:$data_dir/sqlite.db" ) ; // データベースに項目を追加する if ( $uid != "" && $item != "" ) { $insert_sql = sprintf( "insert into Survey( uid , item ) values ( %s , %s ) ;" , $dbh->quote( $uid ) , $dbh->quote( $item ) ) ; $dbh->exec( $insert_sql ) ; // reload処理で追記しないためページを強制的に再表示させる header( "Location: survey-vote.php" ) ; } ?> <html> <head> <title>survey_vote.php</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <form method="get" action="survey-vote.php"> 名前: <input type="text" name="uid" /> 好きな物:<input type="text" name="item" /> <input type="submit" value="投票" /> </form> <?php // データベースの表形式を読み出し、表形式で出力する。 print "<table border='1'>\n" ; print " <tr><td align='center'>uid</td><td align='center'>item</td></tr>\n" ; $select_sql = "select uid,item from Survey ;" ; foreach( $dbh->query( $select_sql ) as list( $t_uid , $t_item ) ) { print " <tr><td>$t_uid</td><td>$t_item</td></tr>\n" ; } print "</table>\n" ; ?> </body> </html>
練習問題(2)
- 上記の survey-vote.php のプログラムを編集し色々な入力方法・出力方法を試してみよ。
- 例えば、入力の item 選択に select や ラジオボタン フォームを使う。
- 例えば、出力結果で、item の投票結果を、棒グラフで出力する。