1. 概要
RETURNING...INTO...句は、INSERT、UPDATE、またはDELETEステートメントと組み合わせて使用されます。これらのステートメントによって影響を受けた行の特定の列の値をPL/SQL変数に代入するために使用されます。これはSELECT...INTO...ステートメントに似ています。INSERT、UPDATE、DELETEの各ステートメントでRETURNING...INTO...が返す結果は異なります。
- DELETEステートメント:削除される前の行の値を返します。
- INSERTステートメント:挿入された後の行の値を返します。
- UPDATEステートメント:更新された後の行の値を返します。
2. 構文
DELETEステートメントでの使用
DELETE FROM table_name [WHERE condition]
RETURNING column1, column2, ... INTO var1, var2, ...;
UPDATEステートメントでの使用
UPDATE table_name
SET column1 = value1, column2 = value2, ...
[WHERE condition]
RETURNING column1, column2, ... INTO var1, var2, ...;
INSERTステートメントでの使用
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
RETURNING column1, column2, ... INTO var1, var2, ...;
注意:RETURNING INTOはINSERT INTO... SELECTステートメントやMERGEステートメントでは使用できません。
3. 使用例
1) データの挿入
DECLARE
new_emp_id employees.employee_id%TYPE;
BEGIN
INSERT INTO employees (employee_id, first_name, last_name, department_id)
VALUES (emp_seq.NEXTVAL, 'TARO', 'YAMADA', 50)
RETURNING employee_id INTO new_emp_id;
COMMIT;
DBMS_OUTPUT.PUT_LINE('挿入された従業員ID: ' || new_emp_id);
END;
出力結果:挿入された従業員ID: 207
2) データの更新
DECLARE
updated_name employees.first_name%TYPE;
updated_dept_id employees.department_id%TYPE;
BEGIN
UPDATE employees
SET department_id = 60
WHERE employee_id = 101
RETURNING first_name, department_id INTO updated_name, updated_dept_id;
COMMIT;
DBMS_OUTPUT.PUT_LINE('従業員名: ' || updated_name || ', 新しい部署ID: ' || updated_dept_id);
END;
出力結果:従業員名: LINA, 新しい部署ID: 60
3) データの削除
DECLARE
deleted_name employees.first_name%TYPE;
deleted_dept_id employees.department_id%TYPE;
BEGIN
DELETE FROM employees
WHERE employee_id = 102
RETURNING first_name, department_id INTO deleted_name, deleted_dept_id;
COMMIT;
DBMS_OUTPUT.PUT_LINE('削除された従業員名: ' || deleted_name || ', 部署ID: ' || deleted_dept_id);
END;
出力結果:削除された従業員名: JIRO, 部署ID: 50
4) 複数行を処理するBULK COLLECT
DECLARE
TYPE dept_id_tbl_type IS TABLE OF departments.department_id%TYPE;
dept_ids dept_id_tbl_type;
BEGIN
UPDATE departments
SET manager_id = 120
RETURNING department_id BULK COLLECT INTO dept_ids;
COMMIT;
FOR i IN 1..dept_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('更新された部署ID: ' || dept_ids(i));
END LOOP;
END;
出力結果:
更新された部署ID: 10
更新された部署ID: 20
更新された部署ID: 30
5) FORALLとBULK COLLECTの組み合わせ
DECLARE
TYPE proj_id_tbl_type IS TABLE OF projects.project_id%TYPE;
TYPE proj_name_tbl_type IS TABLE OF projects.project_name%TYPE;
proj_ids proj_id_tbl_type;
proj_names proj_name_tbl_type := proj_name_tbl_type('Alpha', 'Beta', 'Gamma');
BEGIN
FORALL i IN proj_names.FIRST..proj_names.LAST
INSERT INTO projects (project_id, project_name)
VALUES (proj_seq.NEXTVAL, proj_names(i))
RETURNING project_id BULK COLLECT INTO proj_ids;
COMMIT;
FOR i IN 1..proj_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('プロジェクトID: ' || proj_ids(i) || ', プロジェクト名: ' || proj_names(i) || ' を挿入しました');
END LOOP;
END;
出力結果:
プロジェクトID: 301, プロジェクト名: Alpha を挿入しました
プロジェクトID: 302, プロジェクト名: Beta を挿入しました
プロジェクトID: 303, プロジェクト名: Gamma を挿入しました
6) 動的SQLでの使用
DECLARE
TYPE loc_id_tbl_type IS TABLE OF locations.location_id%TYPE;
loc_ids loc_id_tbl_type;
city_name locations.city%TYPE := 'OSAKA';
BEGIN
EXECUTE IMMEDIATE '
UPDATE locations
SET city = :p_city
WHERE region_id = 81
RETURNING location_id BULK COLLECT INTO :p_loc_ids
' USING city_name, loc_ids;
COMMIT;
FOR i IN 1..loc_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('更新されたロケーションID: ' || loc_ids(i));
END LOOP;
END;
出力結果:
更新されたロケーションID: 1400
更新されたロケーションID: 1401