助け合いフォーラム
Oracle Master Silver SQL 2019(1Z0-071)
問題ID : 26744
問題を開く
次の順番でSQL文を実行した時の説明として、正しいものはどれですか(該当するものを全て選択して下さい)。
なお、それぞれのユーザは、Oracleへの接続には同一アカウント(pingt)を使用して同じデータにアクセスしているものとします。
ユーザーA:
SQL> SELECT d.department_name, e.employee_name
2 FROM departments d JOIN employees e USING (department_id)
3 FOR UPDATE OF e.employee_name NOWAIT; … ①
ユーザーB:
SQL> SELECT employee_id, employee_name FROM employees
2 FOR UPDATE NOWAIT; … ②
SQL> SELECT department_id, department_name FROM departments
2 FOR UPDATE NOWAIT; … ③
ユーザーA:
SQL> UPDATE employees SET salary = 350000 WHERE employee_id = 1020;
SQL> COMMIT;
なお、それぞれのユーザは、Oracleへの接続には同一アカウント(pingt)を使用して同じデータにアクセスしているものとします。
ユーザーA:
SQL> SELECT d.department_name, e.employee_name
2 FROM departments d JOIN employees e USING (department_id)
3 FOR UPDATE OF e.employee_name NOWAIT; … ①
ユーザーB:
SQL> SELECT employee_id, employee_name FROM employees
2 FOR UPDATE NOWAIT; … ②
SQL> SELECT department_id, department_name FROM departments
2 FOR UPDATE NOWAIT; … ③
ユーザーA:
SQL> UPDATE employees SET salary = 350000 WHERE employee_id = 1020;
SQL> COMMIT;
正解
①を実行すると、EMPLOYEES表の該当する行に排他ロックがかかる
②を実行すると、エラーとなる
③を実行すると、検索結果が表示される
解説
設問のSQL文を1つずつ確認してみましょう。
ユーザーA:
SQL> SELECT d.department_name, e.employee_name
2 FROM departments d JOIN employees e USING (department_id)
3 FOR UPDATE OF e.employee_name NOWAIT; … ①
ユーザーB:
SQL> SELECT employee_id, employee_name FROM employees
2 FOR UPDATE NOWAIT; … ②
SQL> SELECT department_id, department_name FROM departments
2 FOR UPDATE NOWAIT; … ③
ユーザーA:
SQL> UPDATE employees SET salary = 350000 WHERE employee_id = 1020;
SQL> COMMIT;
①:SELECT文のFOR UPDATE句に OF 表名.列名 オプションが指定されています。EMPLOYEES表のEMPLOYEE_NAMEが含まれる行にのみ排他ロックがかけられます。
②:①でユーザーAが排他ロックをかけているため、ユーザーBはSELECT文にFOR UPDATE句を指定しても排他ロックをかけることはできません。さらにNOWAITオプションを指定しているので、SELECT文実行後、直ちにエラーとなります。
③:DEPARTMENTS表には排他ロックはかけられていないので、検索後該当する行が表示されます、
以上より、
・①を実行すると、EMPLOYEES表の該当する行に排他ロックがかかる
・②を実行すると、エラーとなる
・③を実行すると、検索結果が表示される
が正解となります。
設問のSQL文の実行結果は次のようになります。
ユーザーA:
SQL> SELECT d.department_name, e.employee_name
2 FROM departments d JOIN employees e USING (department_id)
3 FOR UPDATE OF e.employee_name NOWAIT; … ①
ユーザーB:
SQL> SELECT employee_id, employee_name FROM employees
2 FOR UPDATE NOWAIT; … ②
SQL> SELECT department_id, department_name FROM departments
2 FOR UPDATE NOWAIT; … ③
ユーザーA:
SQL> UPDATE employees SET salary = 350000 WHERE employee_id = 1020;
SQL> COMMIT;
①:SELECT文のFOR UPDATE句に OF 表名.列名 オプションが指定されています。EMPLOYEES表のEMPLOYEE_NAMEが含まれる行にのみ排他ロックがかけられます。
②:①でユーザーAが排他ロックをかけているため、ユーザーBはSELECT文にFOR UPDATE句を指定しても排他ロックをかけることはできません。さらにNOWAITオプションを指定しているので、SELECT文実行後、直ちにエラーとなります。
③:DEPARTMENTS表には排他ロックはかけられていないので、検索後該当する行が表示されます、
以上より、
・①を実行すると、EMPLOYEES表の該当する行に排他ロックがかかる
・②を実行すると、エラーとなる
・③を実行すると、検索結果が表示される
が正解となります。
設問のSQL文の実行結果は次のようになります。
SQLを表示
ユーザーA:
SELECT d.department_name, e.employee_name
FROM departments d JOIN employees e USING (department_id)
FOR UPDATE OF e.employee_name NOWAIT;
ユーザーB:
SELECT employee_id, employee_name FROM employees
FOR UPDATE NOWAIT;
SELECT department_id, department_name FROM departments
FOR UPDATE NOWAIT;
ユーザーA:
UPDATE employees SET salary = 350000 WHERE employee_id = 1020;
SQL> COMMIT;
SELECT d.department_name, e.employee_name
FROM departments d JOIN employees e USING (department_id)
FOR UPDATE OF e.employee_name NOWAIT;
ユーザーB:
SELECT employee_id, employee_name FROM employees
FOR UPDATE NOWAIT;
SELECT department_id, department_name FROM departments
FOR UPDATE NOWAIT;
ユーザーA:
UPDATE employees SET salary = 350000 WHERE employee_id = 1020;
SQL> COMMIT;
参考
通常、Oracle DatabaseではSELECT文の実行時はロックをかけませんが、SELECT文にFOR UPDATE句を指定することで、検索対象となる行に排他ロックをかけることができます。
FOR UPDATE句は次のように指定します。
SELECT 列名 [,列名, ...]
FROM 表名
[WHERE 条件]
FOR UPDATE [OF [表名.]列名] [NOWAIT | WAIT n]
[ORDER BY 列名 [, 列名, ...]];
FOR UPDATE句では、次のオプションを指定できます。
[NOWAIT]
[WAIT n]
[OF 表名.列名]
FROM句に複数の表が指定されている場合は、それぞれの表の対象となる行にロックをかけますが、
OF 表名.列名オプションを指定すると、指定した表名.列名を含む行のみにロックを限定できます。
FOR UPDATE句は次のように指定します。
SELECT 列名 [,列名, ...]
FROM 表名
[WHERE 条件]
FOR UPDATE [OF [表名.]列名] [NOWAIT | WAIT n]
[ORDER BY 列名 [, 列名, ...]];
SQLを表示
ユーザーA:
SELECT employee_id, employee_name, hiredate
FROM employees
WHERE department_id IN (1, 2, 3)
FOR UPDATE;
ユーザーB:
UPDATE employees SET department_id = 5
WHERE hiredate >= '10-04-01';
ユーザーA:
ROLLBACK;
SELECT employee_id, employee_name, hiredate
FROM employees
WHERE department_id IN (1, 2, 3)
FOR UPDATE;
ユーザーB:
UPDATE employees SET department_id = 5
WHERE hiredate >= '10-04-01';
ユーザーA:
ROLLBACK;
FOR UPDATE句では、次のオプションを指定できます。
[NOWAIT]
SQLを表示
ユーザーA:
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE;
ユーザーB:
SELECT employee_id, employee_name, hiredate
FROM employees
WHERE department_id IN (1, 2, 3)
FOR UPDATE NOWAIT;
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE;
ユーザーB:
SELECT employee_id, employee_name, hiredate
FROM employees
WHERE department_id IN (1, 2, 3)
FOR UPDATE NOWAIT;
[WAIT n]
SQLを表示
ユーザーA:
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE;
ユーザーB:
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE WAIT 5;
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE;
ユーザーB:
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE WAIT 5;
[OF 表名.列名]
FROM句に複数の表が指定されている場合は、それぞれの表の対象となる行にロックをかけますが、
SQLを表示
ユーザーA:
SELECT department_name, employee_name, hiredate
FROM departments JOIN employees
USING(department_id)
FOR UPDATE;
ユーザーB:
SELECT department_id, department_name
FROM departments
FOR UPDATE WAIT 3;
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE WAIT 5;
SELECT department_name, employee_name, hiredate
FROM departments JOIN employees
USING(department_id)
FOR UPDATE;
ユーザーB:
SELECT department_id, department_name
FROM departments
FOR UPDATE WAIT 3;
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE WAIT 5;
OF 表名.列名オプションを指定すると、指定した表名.列名を含む行のみにロックを限定できます。
SQLを表示
ユーザーA:
SELECT department_name, employee_name, hiredate
FROM departments JOIN employees
USING(department_id)
FOR UPDATE OF departments.department_name;
ユーザーB:
SELECT department_id, department_name
FROM departments
FOR UPDATE WAIT 5;
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE WAIT 5;
SELECT department_name, employee_name, hiredate
FROM departments JOIN employees
USING(department_id)
FOR UPDATE OF departments.department_name;
ユーザーB:
SELECT department_id, department_name
FROM departments
FOR UPDATE WAIT 5;
SELECT employee_id, employee_name, hiredate
FROM employees
FOR UPDATE WAIT 5;
同一アカウントで、異なったユーザでのデータアクセスについて。
退
退会ユーザ
投稿日 2024/08/12
本問に以下の記述があります。
「それぞれのユーザは、Oracleへの接続には同一アカウント(pingt)を使用して同じデータにアクセスしているものとします。」
この記述による問題状況の考え方としては、
ユーザA, Bは同一のpingtスキーマの表オブジェクトを同時に接続して参照している
といった認識で合っていますでしょうか。
2024/08/13 10:56
問題ID: 29561 の参考に以下の記述がありました。
※ユーザーを作成すると、同じ名前の「スキーマ」も同時に作成されます。スキーマとは、1人のユーザーが所有するオブジェクトの集合です。
なので、「pingtユーザーでログインしている=pingtスキーマを使用している」と言え、同じ表オブジェクトのデータを参照しているということだと判断できるので、 reo_tokeshi さんのご認識の通りかと思います。
コメント
退
退会ユーザ
2024/08/14 23:46
ご回答ありがとうございました。
コメント
この投稿に対して返信しませんか?
b beta
2024/08/19 20:17
a