SQL入門 Oracle9i入門SQL編差分資料
試験範囲として追加された内容
2002年2月より、Oracle9iの内容が含まれた「SQL入門」が始まった。まずは以前の試験との変更点を紹介する。
結合の種類
Oracle8i以前はOracle独自の結合構文のみだったが、Oracle9iではSQL:1999準拠の結合構文が使用できるようになった。
Oracle独自の結合(教科書)
SQL:1999準拠の結合
直積演算
単純結合
・等価結合
・非等価結合
外部結合
内部結合(自己結合、同一表結合)
クロス結合
内部結合
・自然結合
・USING句を使用した結合
・ON句を使用した結合(等価条件、非等価条件)
外部結合
・右側外部結合
・左側外部結合
・完全外部結合
Oracleで言う「内部結合」は、SQL:1999構文では通常の結合(内部結合)と区別されない。ON句を利用して表現できる。
SQL:1999構文での「完全外部結合」は、Oracleでは該当するSQL文は存在しない。(UNION句を利用して2つの結果を連結するという手はあるが・・・)
Oracle9i入門SQL編では、Oracle独自のSQLに加え、SQL:1999準拠の結合構文 も試験範囲に加わった。
9i新機能ではないが、試験の範囲に加わったもの
Oracle9iの新機能というわけではないが、Oracle9i入門SQL編で追加になった試験範囲は次のとおり。
INSERT文内での副問い合わせの使用
DML文でのWITH CHECK OPTIONキーワードの使用
MERGE文
関数・条件式など
NVL2
NULLIF
COALESCE
条件式−CASE文
明示的デフォルト機能(明示的デフォルト値の使用)
名称(呼び方)が変わったもの
従来からの機能だが、8i以前と9i以降で呼び方が変わったものを紹介する。
8i以前 9i以降
比較演算子 比較条件
BETWEEN演算子 BETWEEN条件
機能は使えるが、試験範囲からは外れたもの
1 SQLの種類
Oracle9iでのSQLの種類は次のとおり。
1.データ検索
SELECT
2.データ操作文(DML)
INSERT, UPDATE, DELETE, MERGE
3.データ(トランザクション)制御文(DCL)
COMMIT, ROLLBACK, SAVEPOINT
4.データ定義文(DDL)
CREATE, ALTER, DROP, TRUNCATE, RENAME, GRANT, REVOKE
2 MERGE文(データの挿入または更新)
MERGE文は、Oracle9iから追加されたOracle独自のSQL文で、条件付きで表に行を追加したり、表の中の行を変更できる 。
【構文】
MERGE INTO 表名
USING 元表名 ON (条件)
WHEN MATCHED THEN
UPDATE SET 表名.列名 = 元表名.列名
WHEN NOT MATCHED THEN
INSERT VALUES (元表名.列名);
【機能】
表と元表を比較し、条件と一致すれば更新(UPDATE)を行い、一致しなければ追加(INSERT)を行う。
【使用例】
本社従業員表と名古屋従業員表を照合し、一致する(本社従業員表に存在する)行は「名古屋従業員表のデータ」で「本社従業員表のデータ」を更新し、一致しない(本社従業員表に存在しない)行は、その行を本社従業員表に追加する。
○本社従業員表
従業員番号 従業員名 職種
7782 高橋 課長
7839 林 社長
7934 田村 秘書
○名古屋従業員表
従業員番号 従業員名 職種
7566 松岡 部長
7698 藤原 部長
7782 高橋 部長
[SQL文]
MERGE INTO 本社従業員 h
USING 名古屋従業員 n
ON (h.従業員番号 = n.従業員番号)
WHEN MATCHED THEN
UPDATE SET h.従業員名 = n.従業員名, h.職種 = n.職種
WHEN NOT MATCHED THEN
INSERT VALUES (n.従業員番号, n.従業員名, n.職種);
[実行結果]
従業員番号 従業員名 職種 (変更内容)
7782 高橋 課長 (更新)
7839 林 社長
7934 田村 秘書
7566 松岡 部長 (追加)
7698 藤原 部長 (追加)
従業員番号7782の高橋は両方の表に存在する。「一致する行」なので、本社従業員表のデータは名古屋従業員表のデータに更新される。(従業員名は変わらないが、職種が「課長」から「部長」に変わった)
従業員番号7566の松岡、7698の藤原は、名古屋従業員表にしか存在しないため、本社従業員表に追加される。
3 明示的デフォルト機能
例えばINSERT文で列名を指定してデータを追加するとき、指定しなかった列の値は、デフォルト値が設定されている列ならデフォルト値が、設定されていなければNULL値が格納される。
表の列(受注日)にDEFAULT値が設定されていないとき
INSERT INTO 受注表 (商品番号, 顧客番号, 数量, 受注日)
VALUES (9876, 'A-12345', 25, SYSDATE);
表の列(受注日)にDEFAULT値(SYSDATE)が設定されているとき
INSERT INTO 受注表 (商品番号, 顧客番号, 数量)
VALUES (9876, 'A-12345', 25);
Oracle9iでは、2のケースでDEFAULTキーワード を使用してを指定して、次のように記述できる。
INSERT INTO 受注表 (商品番号, 顧客番号, 数量, 受注日)
VALUES (9876, 'A-12345', 25, DEFAULT );
このように、DEFAULTキーワードを使用して値を設定することを「明示的デフォルト値 を使用する」という。
UPDATE文では次のように指定できる。
UPDATE 受注表
SET 受注日 = DEFAULT
WHERE 〜;
デフォルトキーワードを指定した場合、その列にデフォルト値が設定されていればデフォルト値 が、設定されていなければNULL値 が格納される。
4 SQL:1999構文を使用した直積演算(クロス結合)
Oracleでは、2つ以上の表を結合条件を指定せずに結合 することを直積演算 と呼ぶ。
Oracleでの直積演算の例
SELECT ename, dname
FROM emp, dept;
emp表とdept表の全てのデータの組み合わせが表示される。
では、SQL:1999構文ではどのように記述するのだろうか。
SQL:1999構文での直積演算の構文
SELECT 表名1.列名, 表名2.列名
FROM 表名1 CROSS JOIN 表名2
直積演算する表をCROSS JOIN句で連結 する。SQL:1999ではクロス結合 と呼ぶ。
SQL:1999でのクロス結合の例
SELECT ename, dname
FROM emp CROSS JOIN dept;
5 SQL:1999構文を使用した単純結合(内部結合)
Oracleでの単純結合は、等価結合と非等価結合に分かれるが、SQL:1999では特に区別していない。しかし、Oracle独自のSQLでの結合条件は「列名 = 列名」という書き方しかなかったが、SQL:1999構文ではいろいろな書き方がある。
等価結合の構文1:NATURAL JOIN
[構文]
SELECT 表名1.列名, 表名2.列名
FROM 表名1 NATURAL JOIN 表名2
[機能]
2つの表の同じ列名に基づいて等価結合する(列名は記述しない)
同じ列名であるが、データ型が異なる場合はエラーになる
[例]
Oracle独自のSQLの場合
SELECT ename, emp.deptno, dname
FROM emp, dept
WHERE emp.deptno = dept.deptno;
SQL:1999の場合
SELECT ename, deptno, dname
FROM emp NATURAL JOIN dept;
等価結合の構文2:USING句を使用した結合
[構文]
SELECT 表名1.列名, 表名2.列名
FROM 表名1 JOIN 表名2 USING (列名)
[機能]
2つの表の指定した列名に基づいて等価結合する
同じ列名であるが、データ型が異なる場合はエラーになる
USING句で参照する列には、SQL文のどの箇所にも表名や別名などの修飾子を使用することはできない
[例]
Oracle独自のSQLの場合
SELECT ename, emp.deptno, dname
FROM emp, dept
WHERE emp.deptno = dept.deptno;
SQL:1999の場合
SELECT ename, deptno, dname
FROM emp JOIN dept USING (deptno) ;
等価結合の構文3:ON句を使用した結合
[構文]
SELECT 表名1.列名, 表名2.列名
FROM 表名1 JOIN 表名2 ON 表名1.列名 = 表名2.列名
[機能]
ON句の条件に基づいて結合する
[例]
Oracle独自のSQLの場合
SELECT ename, emp.deptno, dname
FROM emp, dept
WHERE emp.deptno = dept.deptno;
SQL:1999の場合
SELECT ename, emp.deptno, dname
FROM emp JOIN dept ON emp.deptno = dept.deptno ;
[特徴]
結合する列を指定したいときや、任意の条件を指定したいときに利用する
結合条件が他の検索条件(WHERE句)から分離され、コードが分かりやすくなる
等価結合の確認問題
以下の3つの表がある。
[DETP表]
DEPT_ID DEPT_NAME CITY_ID
10 営業 J001
20 教育 E001
30 開発 A002
[CITY表]
CITY_ID CITY COUNTRY_ID
A002 ワシントン 900
E001 ロンドン 500
J001 東京 300
[COUNTRY表]
COUNTRY_ID COUNTRY
300 日本
500 イギリス
900 アメリカ
この3つの表を結合して以下のような結果を得るためのSQL文をそれぞれの構文で作成せよ。
[結合結果]
DEPT_NAME CITY COUNTRY
教育 ロンドン イギリス
開発 ワシントン アメリカ
営業 東京 日本
[SQL]
Oracle結合
SQL:1999構文のNATURAL JOIN
SQL:1999構文のUSING
SQL:1999構文のON
非等価結合の構文
2つ以上の表を結合するとき、結合条件に「=」を使用しない 結合をOracleでは非等価結合 と呼ぶ。
【成績表】
番号 氏名 得点
1 AAAAA 100
2 BBBBB 60
3 CCCCC 75
4 DDDDD 40
5 EEEEE 80
【評価表】
範囲1 範囲2 評価
100 80 A
79 60 B
59 0 C
【非等価結合文】
SELECT t1.番号, t1.氏名, t1.得点, t2.評価
FROM 成績表 t1, 評価表 t2
WHERE t1.得点 BETWEEN t2.範囲1 AND t2.範囲2 ;
【実行結果】
番号 氏名 得点 評価
1 AAAAA 100 A
2 BBBBB 60 B
3 CCCCC 75 B
4 DDDDD 40 C
5 EEEEE 80 A
このように、2つの表を=ではない演算子で結合する結合文を非等価結合 と呼ぶ。
なお、SQL:1999構文では次のように記述する。
【SQL:1999構文での非等価結合】
SELECT t1.番号, t1.氏名, t1.得点, t2.評価
FROM 成績表 t1 JOIN 評価表 t2
ON t1.得点 BETWEEN t2.範囲1 AND t2.範囲2 ;
6 SQL:1999構文を使用した外部結合(左側/右側/完全外部結合)
外部結合 とは、内部結合の結果とともに、一致しない行も戻す結合のことである。
Oracle独自のSQLでは、外部結合は「列名 = 列名(+)」「(+)列名 = 列名」という書き方だったが、SQL:1999構文では次の3タイプがある。
LEFT OUTER JOIN
左側外部結合
RIGHT OUTER JOIN
右側外部結合
FULL OUTER JOIN
完全外部結合(OracleのSQL構文ではできない)
【SQL:1999での外部結合の構文】
SELECT 表名1.列名, 表名2.列名
FROM 表名1 LEFT | RIGHT | FULL OUTER JOIN 表名2 ON (表名1.列名 = 表名2.列名)
ON句の条件に基づいて外部結合を行う
LEFTは(+)を右側に、RIGHTは(+)を左側につけた場合と同じになる
FULLは完全結合
以下、サンプル表を使って各構文を説明する。
【サンプル表】
○従業員表
NAME ADDR JOB DEPT_ID
Syoma Shinagawa Sal 130
Ryotaro Yokoyama Eng 110
Takuma Tokushima Doc 120
Masato Shinagawa Mgn 130
Ayano Tokushima
○部門表
DEPT_ID DEPT_NAME LOC
110 Kensetsu Tokyo
120 Hoken Osaka
130 Kaikei Chiba
140 Kyoiku Kobe
内部結合(復習)
【Oracle独自のSQL】
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e, 部門表 d
WHERE e.dept_id = d.dept_id;
【SQL:1999のON句を用いた内部結合】
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e JOIN 部門表 d
ON e.dept_id = d.dept_id;
【実行結果】
NAME DEPT_NAME DEPT_ID
Ryotaro Kensetsu 110
Takuma Hoken 120
Syoma Kaikei 130
Masato Kaikei 130
※2つの表を内部結合したとき、まだ部門に所属していない従業員「Ayano」は表示されない。また、従業員が所属していない部門140も表示されていない。
左側外部結合
従業員について、部門に所属していなくても全員表示する。
【Oracle独自のSQL】
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e, 部門表 d
WHERE e.dept_id = d.dept_id(+) ;
【SQL:1999の左側外部結合】
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e LEFT OUTER JOIN 部門表 d
ON e.dept_id = d.dept_id;
【実行結果】
NAME DEPT_NAME DEPT_ID
Ryotaro Kensetsu 110
Takuma Hoken 120
Syoma Kaikei 130
Masato Kaikei 130
Ayano
※JOINキーワードの左側(LEFT)にある表についてすべての行を取り出す。
右側外部結合
従業員が所属していなくても、部門についてはすべての行を表示する。
【Oracle独自のSQL】
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e, 部門表 d
WHERE e.dept_id(+) = d.dept_id;
【SQL:1999の右側外部結合】
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e RIGHT OUTER JOIN 部門表 d
ON e.dept_id = d.dept_id;
【実行結果】
NAME DEPT_NAME DEPT_ID
Ryotaro Kensetsu 110
Takuma Hoken 120
Syoma Kaikei 130
Masato Kaikei 130
Kyoiku 140
※JOINキーワードの右側(RIGHT)にある表についてすべての行を取り出す。
完全外部結合
部門に所属していなくても、全従業員の行を表示したい。また、従業員が所属していなくても、全部門の行を表示する。
【Oracle独自のSQL】
Oracleには、完全外部結合を行う構文は存在しない。しかし、UNION句を用いて同様の結果を表示させることはできる。
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e, 部門表 d
WHERE e.dept_id(+) = d.dept_id
UNION
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e, 部門表 d
WHERE e.dept_id = d.dept_id(+);
【SQL:1999の完全外部結合】
SELECT e.name, d.dept_name, d.dept_id
FROM 従業員表 e FULL OUTER JOIN 部門表 d
ON e.dept_id = d.dept_id;
【実行結果】
NAME DEPT_NAME DEPT_ID
Ryotaro Kensetsu 110
Takuma Hoken 120
Syoma Kaikei 130
Masato Kaikei 130
Ayano
Kyoiku 140
※JOINキーワードの右側(RIGHT)にある表についてすべての行を取り出す。
7 新しい関数・条件式
NVL2関数
NULLIF関数
COALESCE関数
CASE式
DECODE式
それぞれを順番に紹介する。
7-1 NVL2関数
列の値がNULLであった場合、別の値に置き換えるNVL関数は教科書で紹介した。
【NVL関数の構文(復習)】
【NVL関数の機能(復習)】
1つ目の引数に指定された列の値を調べ、NULLであれば2つ目の引数の値 を、NULLでなければ列の値 を返す。
【NVL関数の使用例(復習)】
SELECT comm, NVL(comm, 0) FROM emp;
comm NVL(comm, 0)
300 300
0
これに対し、NVL2関数 はNVL関数を拡張したOracle独自の関数で、NULLでない場合の値を指定 することができる。
【NVL2関数の構文】
式1:NULLを含む可能性がある列または式
(任意のデータ型を指定可能)
値1:式1がNULLでない場合に戻す値
値2:式1がNULLである場合に戻す値
(LONG型以外の任意のデータ型を指定可能)
【NVL2関数の機能】
1つ目の引数に指定された列の値を調べ、NULLでなければ2つ目の引数の値 を、NULLであれば列の値 を返す。
【NVL2関数の使用例】
SELECT comm, NVL2(comm, 'データあり', 'データなし') FROM emp;
comm NVL2(comm, 'データあり', 'データなし')
300 データあり
データなし
7-2 NULLIF関数
【NULLIF関数の構文】
【NULLIF関数の機能】
1つ目の式と2つ目の式を調べ、式1=式2であればNULL を、式1≠式2であれば式1 を返す。
ただし、式1にNULLを含めてはならない (全ての結果がNULLになる)。
【NULLIF関数の使用例】
SELECT comm, NVL(comm, 0), NULLIF(NVL(comm, 0), comm) FROM emp;
comm NVL(comm, 0) NULLIF(NVL(comm, 0), comm)
300 300
0 0
7-3 COALESCE関数
【COALESCE関数の構文】
COALESCE(式1, 式2, ・・・, 式n)
【COALESCE関数の機能】
引数に指定された式を先頭から調べ、最初にNULLでない式 を返す。
【COALESCE関数の使用例】
SELECT comm, mgr, coalesce(comm, mgr, 999)
FROM emp;
comm mgr coalesce(comm, mgr, 999)
7902 7902
300 7698 300
999
7-4 CASE式
CASE式またはDECORD式を利用して、SQL文の中でif-then-elseロジックを使うことができる。case式はSQL:1999構文に準拠した条件文である。
【CASE式の構文】
CASE 式 WHEN 条件1 THEN 値1
[ WHEN 条件2 THEN 値2
・
・
ELSE デフォルト値 ] END
【CASE式の機能】
式の値が条件1と一致した場合、値1を返す。条件1と一致しなかった場合、次の条件と比較し、一致した条件の値を返す。
いずれの条件にも一致しなかった場合、デフォルト値を返す。ELSE句を省略した場合はNULLを返す。
【CASE式の使用例】
SELECT
job,
CASE job
WHEN 'SALESMAN' THEN '営業'
WHEN 'PRESIDENT' THEN '社長'
ELSE 'その他'
END "職種"
FROM emp;
job 職種
SALESMAN 営業
CLEAK その他
PRESIDENT 社長
MANAGER その他
7-5 DECODE式
DECODE式は、CASE式のOracle版である。
【DECODE式の構文】
DECODE(式, 条件1, 値1, 条件2, 値2, ・・・, デフォルト値)
【DECODE式の機能】
式の値が条件1と一致した場合、値1を返す。条件1と一致しなかった場合、次の条件と比較し、一致した条件の値を返す。
いずれの条件にも一致しなかった場合、デフォルト値を返す。デフォルト値を省略した場合はNULLを返す。
【DECODE式の使用例】
SELECT
job,
DECODE(job,
'SALESMAN', '営業',
'PRESIDENT', '社長',
'その他'
) "職種"
FROM emp;
job 職種
SALESMAN 営業
CLEAK その他
PRESIDENT 社長
MANAGER その他
7-6 その他教科書には載っていないが試験範囲である関数
【数値関数】
関数名 機能 例
CELI(n) n以上の最も小さい整数を返す CEIL(3.14)は4
FLOOR(n) n以下の最も大きい整数を返す FROOR(3.14)は3
【文字関数】
関数名 機能
RPAD(char1, n, char2) n桁になるようにchar1の右にchar2を埋める (LPADの逆)
TRIM([LEADING | TRAILING | BOTH] [char1 FROM] char2) char2の先頭、最後または両方からchar1を切り捨てる (余分な空白を取るなどに利用)
REPLACE(char1, char2[, char3]) char1の中からchar2を探し、char3に置き換える
8 WITH CHECK OPTIONキーワード
例えばINSERT文で副問い合わせを使用する。
INSERT INTO (SELECT empno, ename, deptno
FROM emp
WHERE deptno = 10)
VALUES (9999, 'ANDO', 20);
この例では、副問い合わせで「deptno = 10」としているが、VALUES句に指定したデータはdeptnoが20である。しかし、副問い合わせのWHERE条件に関係なくデータを追加できる (当たり前だが・・・)。
これを、副問い合わせのWHERE条件に一致しないデータは追加できないように制限をかける ことができる。
INSERT INTO (SELECT empno, ename, deptno
FROM emp
WHERE deptno = 10
WITH CHECK OPTION )
VALUES (9999, 'ANDO', 20);
このように、副問い合わせにWITH CHECK OPTIONキーワードをつけることにより、追加できるデータを制限できる。この例では、次のエラーがでる。
2行でエラーが発生しました。
ORA-01402: ビューのWITH CHECK OPTION WHERE句でエラーが発生しました。
補足
本来、WITH CHECK OPTION WHERE句はビュー(VIEW)を作成するときに指定するキーワードで、これを指定すると、ビューを通したDML文でデータチェックができるようになる。ビューの作成はOracle入門の範囲だが、DML文での副問い合わせでも同じことができるので、試験範囲として加わった。
8 その他の教科書補足
8-1 PL/SQLとは(追加説明)
PL/SQL(Procedural Language/SQL)は、リレーショナルデータベースの標準言語であるSQLに手続き機能を拡張した、オラクル社独自の言語である。OracleServerおよびOracleツール(SQL*Plusなど)で使用できる。
データ検索文、データ操作文(DML)をプロシージャ単位に組み込んで使用するため、「トランザクション処理言語」と呼ばれることもある。
8-2 login.sqlファイル
SQL*Plusではページの縦横の幅などを自由に変更できる。しかし、SQL*Plusを起動するたびにそれらの設定を毎回行うのは面倒である。
SQL*Plusは、起動時にlogin.sqlファイルを読み込み、そのファイルに従った設定を行う。つまり、login.sqlファイルを編集し、自分の好きな環境でSQL*Plusを起動できる。
8-3 暗黙のロールバック
エラーが発生したSQL文は直ちにロールバックされ、変更対象の行に影響は無い(トランザクションではないことに注意)。また、停電やOSのフリーズなどの障害が発生した場合、サーバ再起動後、Oracleは自動的に回復処理を行い、確定していないトランザクションをロールバックする。これらの自動的に行われるロールバックを「暗黙のロールバック」と呼ぶ。