OracleのRETURNING INTO句の使い方

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

タグ: Oracle PL/SQL RETURNING INTO BULK COLLECT DML

6月24日 20:03 投稿