広告 |
---|
■□■□■□■□■□■□■□■□■□■□■□■□■□■□■ 2010年10月17日 Java総合講座 - 初心者から達人へのパスポート 2009年11月開講コース 027号 セルゲイ・ランダウ バックナンバー: http://www.flsi.co.jp/Java_text/ ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■ ------------------------------------------------------- ・現在、このメールマガジンは以下の2部構成になっています。 [1] 当初からのコース:vol.xxx(xxxは番号)が振られています。 これは現在、中級レベルになっています。 [2] 2009年11月開講コース:xxx号(xxxは番号)が振られています。 これは現在、初心者向けのレベルになっています。 ・このメールマガジンは、画面を最大化して見てください。 小さな画面で見ていると、不適切な位置で行が切れてしまう など、問題を起すことがあります。 ・このメールマガジンに掲載されているソース・コード及び 文章は特に断らない限り、すべて筆者が著作権を所有してい ます。また、これらのソース・コードは学習用のためだけに 提供しているものです。 ------------------------------------------------------- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (2009年11月開講コース)027号 当記事はvol.028のリバイバル(revival)版です。 vol.028の内容を最新のEclipse、Javaに基づいて書き直しています。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ======================================================== ◆ 01.データベース(続き) ======================================================== 今回は、前回のEMPLOYEEテーブルとDEPARTMENTテーブルを 実際に作成してみましょう。 まず、カラム名は以下のようにすることにします。 --------------------------------------------------- [EMPLOYEEテーブルのカラム] 社員番号、氏名、生年月日、所属部門コード EMP_NUM, NAME, DATE_OF_BIRTH, DEPART_NUM --------------------------------------------------- --------------------------------------------------- [DEPARTMENTテーブルのカラム] 部門コード、部門名、オフィス所在地 DEPART_NUM, DEPART_NAME, LOCATION --------------------------------------------------- ところで、EMPLOYEEテーブルのDEPART_NUMはDEPARTMENTテー ブルのDEPART_NUMを参照する外部キーでしたね。 このように外部キーを使って他のテーブルのデータを参照し ている場合には、RDBMSが参照の整合性をチェックしますの で、注意してください。 たとえば、もしEMPLOYEEテーブルを先に作成してデータを 入れようとすると、それが参照しているDEPARTMENTテーブ ルのデータが存在しないので整合性が取れないことになり、 RDBMSがエラーを返します。 したがって、EMPLOYEEテーブルよりも、DEPARTMENTテーブル のほうを先に作成してデータを入れておきます。 (以後、SQL文の最後には「;」を付けることにします。) CREATE TABLE DEPARTMENT (DEPART_NUM INTEGER NOT NULL, DEPART_NAME CHAR(50), LOCATION CHAR(80), PRIMARY KEY (DEPART_NUM)); H2 Consoleを起動して、実際に上記のSQLを実行してみま しょう。 続いて、DEPARTMENTテーブルにデータを入れておきましょ う。 INSERT INTO DEPARTMENT VALUES (0, '社長直属', 'Xビル3階'); INSERT INTO DEPARTMENT VALUES (1, '総務課', 'Xビル2階'); INSERT INTO DEPARTMENT VALUES (2, '営業課', 'Xビル1階'); では、次にEMPLOYEEテーブルを作成しましょう。 CREATE TABLE EMPLOYEE (EMP_NUM INTEGER NOT NULL, NAME CHAR(50), DATE_OF_BIRTH DATE, DEPART_NUM INTEGER NOT NULL, PRIMARY KEY (EMP_NUM), FOREIGN KEY (DEPART_NUM) REFERENCES DEPARTMENT (DEPART_NUM) ON DELETE CASCADE); ここで新しいキーワードが出てきましたので、説明しておき ましょう。 上記のDATEというキーワードは標準のSQLで扱えるデータの型 の一つで、日付のデータを設定するための型になっています。 詳しくは後述します。 上記のFOREIGN KEYというのは外部キー(foreign key)を意味 するキーワードでその右側の括弧の中にDEPART_NUMと書いてあ るのは、このテーブル内のDEPART_NUMというカラムが外部キー になっていることを指定しているものです。 そしてその外部キーがどのテーブルのどのカラムを参照してい るのかを指定しているのがその右側のREFERENCESというキーワー ドです。 そしてREFERENCESの右側に DEPARTMENT (DEPART_NUM) と書いてあるのは、DEPARTMENTテーブルのDEPART_NUMというカラ ムを参照することを指定するものです。 また、さらにその右側に書いてある ON DELETE CASCADE というキーワードはこの外部キーが参照しているDEPARTMENTテー ブルにおいて、ある行が削除されたとき、その行を参照していた (つまりその行のDEPART_NUMカラムの値を外部キーの値として持っ ていた)EMPLOYEEテーブルの行も削除することを意味します。 たとえば、DEPART_NUMが1の'総務課'が廃止されたとして、 DEPARTMENTテーブルの中の'総務課'の行を削除すると、自動的に EMPLOYEEテーブルの中のDEPART_NUMが1の行、つまり'総務課'に所属 していた社員の行も削除されることになります。 これは参照の整合性が維持されている例としてはいいのですが、 総務課が廃止されたらそこに所属していた社員も全員首になると いうことですから(冗談ですが)、あまりいい例ではありませんね。 というわけで、少し変更しましょう。 通常は、部署が廃止されてもそこに所属していた社員が別の部署に 異動になるか、さもなければしばらくの間は社長直属などの一時的 な所属があてられることになるでしょうから、そのように指定を 変更してみましょう。 さきほどの ON DELETE CASCADE の代わりに ON DELETE SET DEFAULT を指定し、 DEPART_NUM INTEGER NOT NULL の右側にDEFAULT 0をつけて DEPART_NUM INTEGER NOT NULL DEFAULT 0 という指定に書き換えてみましょう。 下にSQL文全体を掲載します。 CREATE TABLE EMPLOYEE (EMP_NUM INTEGER NOT NULL, NAME CHAR(50), DATE_OF_BIRTH DATE, DEPART_NUM INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (EMP_NUM), FOREIGN KEY (DEPART_NUM) REFERENCES DEPARTMENT (DEPART_NUM) ON DELETE SET DEFAULT); この DEPART_NUM INTEGER NOT NULL DEFAULT 0 の指定によって、DEPART_NUMカラムについてはデフォルト値 (値を明示しないときに自動的に設定される値)が0になり、 FOREIGN KEYの ON DELETE SET DEFAULT の指定によってDEPARTMENTテーブルの行の削除時にはそれを 参照しているEMPLOYEEテーブルの行が削除されるのではなく、 EMPLOYEEテーブルの該当する行のDEPART_NUMカラムの値がデ フォルト値(ここでは0)に設定されることになります。 そして、社長直属というのも一つの部署とみなしてその DEPART_NUMの値を0としておくと、他の部署が廃止されたとき にはその部署に所属していた社員は自動的に社長直属に変更さ れるということになります。 では、上のCREATE TABLE文をH2 Consoleに入力してください。 続いて、EMPLOYEEテーブルにデータを入れておきましょう。 INSERT INTO EMPLOYEE VALUES (1, '舟木和子', '1970-11-12', 1); INSERT INTO EMPLOYEE VALUES (2, '安部泰三', '1960-10-12', 1); INSERT INTO EMPLOYEE VALUES (3, '長内順平', '1986-08-12', 2); 上記のSQL文を見ればわかるように、先ほどのDATEという型に 対する値は 'YYYY-MM-DD' という形式で指定することになっています。 ここで、YYYYは4桁の(西暦の)年の数字、MMは2桁の月の数字、 DDは2桁の日の数字を意味します。 たとえば1970年11月12日は'1970-11-12'と指定するわけです。 では、次に DELETE FROM DEPARTMENT WHERE DEPART_NUM=2; を実行することによってDEPARTMENTテーブルからDEPART_NUMの値 が2の行を削除してみてください。 そして SELECT * FROM EMPLOYEE で、EMPLOYEEテーブルの中の DEPART_NUMの値が2だった行、つまり'長内順平'さんの行を見て みるとDEPART_NUMの値が自動的に0に変わることがわかりますね。 しかし、ここで、「社長直属を一つの部署とみなすのはおかしい のではないの?」「社長直属って部署じゃないんじゃないの?」と、 疑問を呈する人もいるかもしれません。 もし、そういうことにこだわるのであれば、次のような指定も可能 です。 CREATE TABLE EMPLOYEE (EMP_NUM INTEGER NOT NULL, NAME CHAR(50), DATE_OF_BIRTH DATE, DEPART_NUM INTEGER, PRIMARY KEY (EMP_NUM), FOREIGN KEY (DEPART_NUM) REFERENCES DEPARTMENT (DEPART_NUM) ON DELETE SET NULL); このSQL文ではDEPART_NUMにNOT NULLの指定がないので、DEPART_NUM にはNULL(データが空)も許容されます。 また、 FOREIGN KEY (DEPART_NUM) のREFERENCESに対して ON DELETE SET NULLが指定されているので、DEPARTMENTテーブル の行の削除時にはそれを参照しているEMPLOYEEテーブルの該当す る行のDEPART_NUMカラムの値がNULL(空っぽ)に設定されること になります。 したがって、DEPART_NUMカラムの値がNULL(空っぽ)の場合を 社長直属と定義することにすると、先ほどのように社長直属を (DEPART_NUMが0の)一つの部署とみなしてDEPARTMENTテーブル にデータを入れておくような必要はなくなります。 ただし、この場合はDEPART_NUMの値を設定し忘れてもDEPART_NUM の値がNULLになってしまい、データ入力する人が間違えると、 やたらに社長直属の社員が増えるということにもなりかねません。 というわけで、NULLの使用はできるだけ避けたほうがいいのです。 主キーや外部キーはNOT NULLを指定してNULLを使用できないように するのが原則です。 NOT NULLを指定しておけば、データ入力時に値を設定し忘れると エラーになるので気が付きます。 では、次に、こうして作られたEMPLOYEEテーブルとDEPARTMENTテー ブルを組み合わせてデータを表示したいときにはどうするのかお話 しましょう。 たとえば、社員のデータを表示したいと思って SELECT * FROM EMPLOYEE というSQL文を実行しても、所属部署については数字しか表示され ませんが、所属部署についての詳しいデータをDEPARTMENTテーブル から取ってきて社員のデータと一緒に並べたいときには、たとえば 次のようなSQL文を指定します。 SELECT * FROM EMPLOYEE, DEPARTMENT WHERE EMPLOYEE.DEPART_NUM = DEPARTMENT.DEPART_NUM; ここで、FROMの後ろにEMPLOYEE, DEPARTMENTというようにテーブル名 を複数並べると、複数のテーブルからデータを取り出すことができ ます。 また WHERE EMPLOYEE.DEPART_NUM = DEPARTMENT.DEPART_NUM はEMPLOYEEテーブルのDEPART_NUMカラムの値とDEPARTMENTテーブル のDEPART_NUMカラムの値を照らし合わせて、それらが互いに等しい行 のデータを取り出すことを意味します。 しかし、こうやってデータを取り出すと、返ってきたリストの中には EMPLOYEEテーブルのDEPART_NUMカラムの値とDEPARTMENTテーブルの DEPART_NUMカラムの値の両方が含まれ、それらは互いに同じ値ですから 無駄でうっとうしく見えるかも知れません。 うっとうしいと思う人は、下記のように、表示したいカラムだけを 一つ一つ明示しましょう。 SELECT EMP_NUM, NAME, DATE_OF_BIRTH, EMPLOYEE.DEPART_NUM, DEPART_NAME, LOCATION FROM EMPLOYEE, DEPARTMENT WHERE EMPLOYEE.DEPART_NUM = DEPARTMENT.DEPART_NUM; このとき、DEPART_NUMカラムのようにEMPLOYEEテーブルとDEPARTMENTテー ブルのどちらにも同名で含まれるカラムについては、EMPLOYEE.DEPART_NUM のように「テーブル名.カラム名」の形式でテーブル名も明確にしてお きます。 次回は、データベースをもう少し複雑にして実用的なレベルに近づけ、 データベースを使ったJavaのアプリケーション開発の説明に入っていき ます。 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ★ホームページ: http://www.flsi.co.jp/Java_text/ ★このメールマガジンは 「まぐまぐ(http://www.mag2.com)」 を利用して発行しています。 ★バックナンバーは http://www.flsi.co.jp/Java_text/ にあります。 ★このメールマガジンの登録/解除は下記Webページでできます。 http://www.mag2.com/m/0000193915.html ★このメールマガジンへの質問は下記Webページにて受け付けて います。わからない所がありましたら、どしどしと質問をお寄 せください。 http://www.flsi.co.jp/Java_text/ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ Copyright (C) 2010 Future Lifestyle Inc. 不許無断複製 |