Oracleデータベースエンジニアとしての実力を証明するORACLE MASTER資格。その入り口であるBronze資格の取得は難しくない。本連載と、同時掲載中の連載「Bronze DBA講座」で合格を目指そう!
本連載第8回「SELECT文中のSELECT文、副問い合わせ」、第9回「副問い合わせの構文を覚える」の2回にわたり、副問い合わせによって問い合わせ結果をSQL文の条件に使用する方法を紹介しました。第10回に当たる今回は、データ操作について学びましょう。
表に新しく行を挿入するには、INSERT文を使用します。
・列名:表の列定義順にすべての列を指定するのであれば不要・値:列定義順に実際の行を構成する列値を指定
表定義には存在するのに列名として指定しない場合、その列にはNULL値が格納されます(列にデフォルト値が設定されていれば、その値を格納)。
例: SQL> INSERT INTO emp(empno, ename, deptno) VALUES(8000, 'TEST', 10); SQL> SELECT * FROM emp WHERE empno=8000; EMPNO ENAME JOB COMM DEPTNO ---------- ---------- ---------- ... ---------- ---------- 8000 TEST 10 |
INSERT文では、VALUES句の代わりに副問い合わせを使用することができます。副問い合わせの結果は、INSERTの列の数とデータ型に一致する必要があります。
例: SQL> INSERT INTO emp2 SELECT * FROM emp; |
次の表定義を確認してください。
EMPNO NUMBER(4) 主キー ENAME VARCHAR2(15) JOB VARCHAR2(10) DEPTNO NUMBER(2) |
エラーとならずに実行できる文を3つ選択しなさい。
a.INSERT INTO emp VALUES (1000,'SCOTT','CLERK');
b.INSERT INTO emp(ename,job) VALUES ('SCOTT','CLERK');
c.INSERT INTO emp(empno) VALUES (1000);
d.INSERT INTO emp VALUES (1000,'SCOTT','CLERK',10);
e.INSERT INTO emp(ename, job, empno) VALUES (1000,'SCOTT','CLERK');
f.INSERT INTO emp(empno, job) VALUES (1000,'CLERK');
正解:c、d、f
この問題では、empno列が主キーですので、INSERT時にも必ず値を格納する必要があります。そこに着目すると、選択肢bはempno列をINSERTの列リストに含めていないのでエラーとなります。
選択肢eは、INSERTの列リストを使用していますが、INSERT列リストとVALUESリストの順番がずれているためエラーになってしまいます。選択肢eの方法で記述するのであれば、次のように記述します。
選択肢aはINSERTの列リストを使用していないので、すべての列値をVALUESリストに含める必要がありますが、1列足りないのでエラーとなります。残りのc、d、fが正解となります。
表内の既存行を変更するには、UPDATE文を使用します。
WHERE句を使用せずにUPDATE文を実行すると、その表のすべての行が更新されます。
例: SQL> UPDATE emp SET job='SALESMAN', sal=2000 WHERE empno=8000; SQL> SELECT * FROM emp WHERE empno=8000; EMPNO ENAME JOB SAL COMM DEPTNO ---------- ---------- ---------- ... ---------- ---------- ---------- 8000 TEST SALESMAN 2000 10 |
EMP表の従業員番号が7369と7788の行を次の要件で更新します。
・職種(JOB)は、デフォルト値を使用する
・歩合給(COMM)は、100とする
・部門番号(deptno)は、置換変数を使用して値を入力する
・入社日(hiredate)は、デフォルト値を使用するがNULLにすることもできる
この要件を満たしている文を選択しなさい。
a.
UPDATE emp SET
job = DEFAULT,
comm = 100,
deptno = &deptno,
hiredate = DEFAULT OR NULL
WHERE empno IN (7369, 7788);
b.
UPDATE emp SET
job = DEFAULT,
comm = 100,
deptno = &deptno,
hiredate = DEFAULT
WHERE empno IN (7369, 7788);
c.
UPDATE emp SET
job = DEFAULT,
comm = 100,
hiredate = DEFAULT
WHERE empno IN (7369, 7788)
AND deptno = &deptno;
d.
UPDATE emp SET
job IS DEFAULT,
comm = 100,
deptno = &deptno,
hiredate IS DEFAULT
WHERE empno IN (7369, 7788);
正解:b
表の列に設定したデフォルト値を利用するには、値として「DEFAULT」キーワードを使用します。このキーワードはOracle9iより使用可能になっており、INSERT時やUPDATE時に使用できます。選択肢aの「= DEFAULT OR NULL」や選択肢dの「IS DEFAULT」のような使い方はできません。
また、実行時に値を入力させるのであれば、置換変数を使用します。SQL*Plus、iSQL*Plus限定ですが、「&置換変数」にて実行時入力ができます。
一見すると選択肢cは間違っていませんが、問題の要件に合っていません。選択肢cは、「従業員番号7369または7788、かつ指定した部門番号の従業員を更新」になってしまいます。問題要件はよく読むようにしましょう。残りのbが正解となります。
表内の既存行を削除するには、DELETE文を使用します。
DELETE [FROM] 表名 [WHERE 条件式];
WHERE句を使用せずにDELETE文を実行すると、その表のすべての行が削除されますが、表定義は残ります。
列を削除するにはALTER TABLE文、表そのものを削除するにはDROP TABLE文を使用します。間違わないようにしましょう。
例: SQL> DELETE FROM emp WHERE empno=8000; SQL> SELECT * FROM emp WHERE empno=8000; レコードが選択されませんでした。 |
次の文を確認してください。
DELETE emp; |
この文の結果として正しいものを選択しなさい。
a.EMP表の表定義が削除される
b.EMP表のすべての行が削除される
c.ROLLBACKできない
d.構文エラーのため、実行できない
正解:b
ANSIで定義しているSQLでは「DELETE FROM 表名」ですが、OracleのDELETE文では、FROM句は任意です。省略しても構文エラーにはなりません(選択肢d)。
DELETE文でWHERE句を省略すると、すべての行が削除されます(正解b)。しかし、空のテーブルになるだけで、表としての定義は残されています(選択肢a)。
また、DELETE文はDMLですから、COMMITするまでは確定されず、ROLLBACK(取り消し)することができます(選択肢c)。
表構造は残し、表内のすべての行を削除する方法としてWHERE句なしのDELETE文がありますが、TRUNCATE文を使用すると、DELETE文よりも高速に行を削除することができます。
ただし、DELETE文はDMLですが、TRUNCATE文はDDL(データ定義言語)であり、暗黙のうちにコミットされます。そのため、取り消し(ROLLBACK)することができません。
例: SQL> SELECT COUNT(*) FROM emp2; COUNT(*) ---------- 14 SQL> TRUNCATE TABLE emp2; 表が切り捨てられました。 SQL> SELECT COUNT(*) FROM emp2; COUNT(*) ---------- 0 |
次の文を確認してください。
TRUNCATE TABLE emp; |
この文の特徴を3つ選択しなさい。
a.EMP表の定義が削除される
b.EMP表の定義は残される
c.EMP表の領域は残される
d.EMP表の領域は解放される
e.DESC empとすると、結果が表示されない
f.表の所有者かDROP ANY TABLE権限を持っている必要がある
正解:b、d、f
TRUNCATE文は、表の定義を残したまま、高速に表の行のみを削除します。見掛け上の動作は、WHERE句なしのDELETE文と同じです。表の定義は削除されません(選択肢a、正解b)。定義が残されるので、SQL*PlusのDESCコマンドを使用して定義を確認することが可能です(選択肢e)。
DELETE文の場合は、一度使用した領域フラグ(高水位標、High Water Markという)は変化しませんが、TRUNCATE文の場合は領域が解放されます(選択肢c、正解d)。
また、Oracleサーバの場合、表の所有者はその表に対するひととおりの権限を持ちますがほかのユーザーが所有する表に対しては何らかの権限が必要です。正解fのDROP ANY TABLE権限はほかのユーザーが所有する表を削除できる権限で、TRUNCATE文の実行にもこの権限が必要です。
DMLによる表データの操作は、1つ1つの操作を確定する(コミット)のではなく、関連する一連の操作をまとめて確定するべきであると考えられています。一連の操作が確定できないときは、すべてを取り消す(ロールバック)ことでデータの整合性を保証します。このような一連の操作を「トランザクション」と呼びます。
Oracleデータベースでは、DDLとDCL(データ制御言語)は個々の文を1つのトランザクションとして扱いますが、DMLでは次のいずれかのイベントが発生するまでを1つのトランザクションとして扱います。
DDLが発行されると、そのセッションで発行されていたトランザクションは自動的にコミットされます。DDLだけで1つのトランザクションになるので、DDL後のDMLで新たなトランザクションが開始されます。
SQL*PlusやiSQL*Plusでは、1つのトランザクションが終わると、自動的に次のトランザクションが開始するようになっています。
ロールバックでは、事前に「セーブポイント」を設定しておくことで、トランザクション全体ではなく、セーブポイントまでのロールバックを行うこともできます。
図2のようなトランザクションの場合、ROLLBACK文によって次のように処理が行われます。
ロールバックされる中に含まれるセーブポイントは消去されます。図2の例で「ROLLBACK TO A」を実行すると、セーブポイントAは残りますが、セーブポイントBは消去されます。
トランザクションを完了する文を2つ選択しなさい。
a.DELETE FROM emp;
b.ROLLBACK TO SAVEPOINT a;
c.GRANT SELECT ON emp TO hr;
d.ALTER TABLE emp ADD COLUMN jobs VARCHAR2(10);
e.SELECT empno, ename FROM emp ORDER BY sal;
正解:c、d
前回、宿題とした問題です。トランザクションは、COMMITやROLLBACK文によってだけでなく、ALTERなどのDDL(正解d)やGRANTなどのDCL(正解c)によって暗黙にコミットされます。DDLやDCLを使うときは注意しましょう。DDLに関しては、次回「オブジェクトの作成および管理」で解説します。
紛らわしいのが選択肢bだと思います。選択肢bは、「セーブポイントまでロールバック」ですから、トランザクションは続行しています。選択肢a、選択肢eのようなDMLでは、暗黙コミットはされません。
Oracleデータベースでは、あるトランザクションで変更中のデータをほかのトランザクションから参照することはできません。これはトランザクションが確定されない状態を読み取ることによるデータの不整合を防止するための動作です。
代わりに、トランザクションが変更する前のデータを参照することができます。変更前のデータは確定済みのデータですから、整合が取れた状態で参照することができます。このような動作のことを「読み取り一貫性」といいます。読み取り一貫性は、トランザクションによってデータが変更される際、「UNDOブロック」と呼ばれる変更前のイメージを保存しておくことで提供されます。
図3では、トランザクションAが変更したデータ(20という値)を別のトランザクションBが参照できるのは、トランザクションAがコミットされた後です。
次の内容をチェックしておきましょう。
次回は、「オブジェクトの作成および管理」を確認します。次の宿題を解いておいてください。
次の文を確認してください。
CREATE TABLE orders( empno NUMBER(4) UNIQUE, ename VARCHAR2(15) NOT NULL, sal NUMBER(7,2) CHECK(sal>0), ord_id NUMBER(3), ord_status CHAR(2), CONSTRAINT orders_pk PRIMARY KEY(ord_id, ord_status)); |
この文で自動的に索引が作成される列を2つ選択しなさい。
a.empno
b.ename
c.sal
d.ord_id
e.ord_status
f.ord_idとord_statusの複合
Copyright © ITmedia, Inc. All Rights Reserved.