レコード変数への値の代入
レコード変数とは、レコード変数またはコンポジット変数のレコード・コンポーネントのいずれかを意味します。
どのレコード変数にも、各フィールドには個別に値を代入できます。
修飾式を使用して値を割り当てることができます。
場合によっては、あるレコード変数の値を別のレコード変数に代入できます。
データベースの表またはビュー内の行の全体または一部を表すレコード変数の場合は、対象となる行をレコード変数に代入できます。
ここでのトピック
修飾式を使用したRECORD型変数への値の代入
修飾式の位置関連付けまたは名前関連付け集計を使用して、RECORD
型の変数に値を代入できます。
修飾式は式要素を組み合せて、RECORD
型の値を作成します。集計は複合型の値を定義します。修飾式を使用して、RECORD
型に値を代入できます。位置と名前の関連付けは、RECORD
型の修飾式に使用できます。位置関連付けが同じ構造体内の名前関連付けに従っていない場合もあります(その逆も同様です)。最後のオプションとして、位置関連付けと名前関連付けの後にその他選択を指定できます。
このコンテキストの修飾式の構造は次のとおりです。
qualified_expression ::= typemark ( aggregate ) aggregate ::= ( positional_association | named_association ) [ others_choice ] positional_association ::= ( expr )+ named_association ::= identifier => expr [,]+
例6-52 修飾式を使用したRECORD型変数への値の代入
この例は、RECORD
型変数の宣言、初期化および定義を示しています。
パッケージpkg内でrec_t型が定義されていて、一部が初期化されています。
その型を使用して変数v_rec1が宣言され、位置集計を使用して初期値が代入されています。
その型を使用して変数v_rec2も宣言され、名前関連付け集計を使用して初期値が代入されています。
変数v_rec3にはNULL値が代入されています。
プロシージャprint_recはローカル変数v_rec1の値を表示し、続いてプロシージャ・パラメータpi_rec変数値を表示します。プロシージャにパラメータが渡されない場合は、プロシージャ定義に設定されている初期値が表示されます。
Live SQL:
この例は、Oracle Live SQLの「18c修飾式を使用したRECORD型変数への値の代入」で表示および実行できます。
CREATE PACKAGE pkg IS
TYPE rec_t IS RECORD
(year PLS_INTEGER := 2,
name VARCHAR2 (100) );
END;
/
DECLARE
v_rec1 pkg.rec_t := pkg.rec_t(1847,'ONE EIGHT FOUR SEVEN');
v_rec2 pkg.rec_t := pkg.rec_t(year => 1, name => 'ONE');
v_rec3 pkg.rec_t := pkg.rec_t(NULL,NULL);
PROCEDURE print_rec ( pi_rec pkg.rec_t := pkg.rec_t(1847+1, 'a'||'b')) IS
v_rec1 pkg.rec_t := pkg.rec_t(2847,'TWO EIGHT FOUR SEVEN');
BEGIN
DBMS_OUTPUT.PUT_LINE(NVL(v_rec1.year,0) ||' ' ||NVL(v_rec1.name,'N/A'));
DBMS_OUTPUT.PUT_LINE(NVL(pi_rec.year,0) ||' ' ||NVL(pi_rec.name,'N/A'));
END;
BEGIN
print_rec(v_rec1);
print_rec(v_rec2);
print_rec(v_rec3);
print_rec();
END;
/
2847 TWO EIGHT FOUR SEVEN 1847 ONE EIGHT FOUR SEVEN 2847 TWO EIGHT FOUR SEVEN 1 ONE 2847 TWO EIGHT FOUR SEVEN 0 N/A 2847 TWO EIGHT FOUR SEVEN 1848 ab
あるレコード変数から別のレコード変数への代入
次の場合にかぎり、あるレコード変数の値を別のレコード変数に代入できます。
-
2つの変数は同じ
RECORD
型を持ちます。 -
代入先の変数が
RECORD
型で、代入元の変数が%ROWTYPE
でそれぞれ宣言され、両者のフィールドの数と順序が一致し、対応するフィールドのデータ型が同じである場合。
コンポジット変数のレコード・コンポーネントの場合は、コンポジット変数の型が一致している必要があります。
例6-53 同じRECORD型のレコードから別のレコードへの代入
この例では、name1とname2が同じRECORD型であるため、name1の値をname2に代入できます。
DECLARE TYPE name_rec IS RECORD ( first employees.first_name%TYPE DEFAULT 'John', last employees.last_name%TYPE DEFAULT 'Doe' ); name1 name_rec; name2 name_rec; BEGIN name1.first := 'Jane'; name1.last := 'Smith'; DBMS_OUTPUT.PUT_LINE('name1: ' || name1.first || ' ' || name1.last); name2 := name1; DBMS_OUTPUT.PUT_LINE('name2: ' || name2.first || ' ' || name2.last); END; /
結果:
name1: Jane Smith name2: Jane Smith
例6-54 RECORD型のレコードへの%ROWTYPEレコードの代入
この例では、代入先の変数がRECORD
型、代入元の変数が%ROWTYPE
でそれぞれ宣言され、両者のフィールドの数と順序が一致し、対応するフィールドのデータ型が同じです。
DECLARE TYPE name_rec IS RECORD ( first employees.first_name%TYPE DEFAULT 'John', last employees.last_name%TYPE DEFAULT 'Doe' ); CURSOR c IS SELECT first_name, last_name FROM employees; target name_rec; source c%ROWTYPE; BEGIN source.first_name := 'Jane'; source.last_name := 'Smith'; DBMS_OUTPUT.PUT_LINE ( 'source: ' || source.first_name || ' ' || source.last_name ); target := source; DBMS_OUTPUT.PUT_LINE ( 'target: ' || target.first || ' ' || target.last ); END; /
結果:
source: Jane Smith target: Jane Smith
例6-55 同じRECORD型のネストしたレコードから別のレコードへの代入
この例では、あるネストしたレコードの値を別のネストしたレコードに代入します。これらのネストしたレコードは同じRECORD
型を持ちますが、これらがネストされているレコードは同じではありません。
DECLARE TYPE name_rec IS RECORD ( first employees.first_name%TYPE, last employees.last_name%TYPE ); TYPE phone_rec IS RECORD ( name name_rec, -- nested record phone employees.phone_number%TYPE ); TYPE email_rec IS RECORD ( name name_rec, -- nested record email employees.email%TYPE ); phone_contact phone_rec; email_contact email_rec; BEGIN phone_contact.name.first := 'John'; phone_contact.name.last := 'Smith'; phone_contact.phone := '1-650-555-1234'; email_contact.name := phone_contact.name; email_contact.email := ( email_contact.name.first || '.' || email_contact.name.last || '@' || 'example.com' ); DBMS_OUTPUT.PUT_LINE (email_contact.email); END; /
結果:
John.Smith@example.com
レコード変数への行の全体または一部の代入
データベースの表またはビュー内の行の全体または一部を表すレコード変数の場合は、対象となる行をレコード変数に代入できます。
ここでのトピック
SELECT INTOを使用した行のレコード変数への代入
単純なSELECT
INTO
文の構文は次のとおりです。
SELECT select_list INTO record_variable_name FROM table_or_view_name;
select_list
の各列に対して、レコード変数の中には、対応する型互換のフィールドが存在している必要があります。select_list
内の列は、レコード・フィールドと同じ順序で並んでいる必要があります。
関連項目:
構文の詳細は、「SELECT INTO文」を参照してください
例6-56 SELECT INTOを使用したレコード変数への値の代入
この例では、レコード変数rec1
は、employees
表の行の一部(列last_name
およびemployee_id
)を表しています。SELECT
INTO
文は、job_id
が'AD_PRES'
の行をemployees
から選択し、選択した行の列last_name
およびemployee_id
の値をrec1
の対応するフィールドに代入しています。
DECLARE TYPE RecordTyp IS RECORD ( last employees.last_name%TYPE, id employees.employee_id%TYPE ); rec1 RecordTyp; BEGIN SELECT last_name, employee_id INTO rec1 FROM employees WHERE job_id = 'AD_PRES'; DBMS_OUTPUT.PUT_LINE ('Employee #' || rec1.id || ' = ' || rec1.last); END; /
結果:
Employee #100 = King
FETCHを使用した行のレコード変数への代入
単純なFETCH
文の構文は次のとおりです。
FETCH cursor INTO record_variable_name;
カーソルは問合せに関連付けられています。問合せにより選択されるすべての列に対して、レコード変数の中には、対応する型互換のフィールドが存在している必要があります。カーソルは、明示カーソルまたは強いカーソル変数のいずれかである必要があります。
例6-57 ファンクションが戻すレコードへのFETCHによる値の代入
この例では、RECORD
型EmpRecTyp
の各変数は、employees
表の行の一部(列employee_id
およびsalary
)を表しています。カーソルおよびファンクションの両方は、型EmpRecTyp
の値を戻します。このファンクションでは、列employee_id
およびsalary
の値がFETCH
文により型EmpRecTyp
のローカル変数の対応するフィールドに代入されます。
DECLARE
TYPE EmpRecTyp IS RECORD (
emp_id employees.employee_id%TYPE,
salary employees.salary%TYPE
);
CURSOR desc_salary RETURN EmpRecTyp IS
SELECT employee_id, salary
FROM employees
ORDER BY salary DESC;
highest_paid_emp EmpRecTyp;
next_highest_paid_emp EmpRecTyp;
FUNCTION nth_highest_salary (n INTEGER) RETURN EmpRecTyp IS
emp_rec EmpRecTyp;
BEGIN
OPEN desc_salary;
FOR i IN 1..n LOOP
FETCH desc_salary INTO emp_rec;
END LOOP;
CLOSE desc_salary;
RETURN emp_rec;
END nth_highest_salary;
BEGIN
highest_paid_emp := nth_highest_salary(1);
next_highest_paid_emp := nth_highest_salary(2);
DBMS_OUTPUT.PUT_LINE(
'Highest Paid: #' ||
highest_paid_emp.emp_id || ', $' ||
highest_paid_emp.salary
);
DBMS_OUTPUT.PUT_LINE(
'Next Highest Paid: #' ||
next_highest_paid_emp.emp_id || ', $' ||
next_highest_paid_emp.salary
);
END;
/
結果:
Highest Paid: #100, $24000 Next Highest Paid: #101, $17000
PL/SQLレコード変数に行を戻すSQL文の使用
SQLのINSERT
文、UPDATE
文およびDELETE
文には、影響のある行をPL/SQLレコード変数に戻すことができる、オプションのRETURNING
INTO
句があります。
この句の詳細は、「RETURNING INTO句」を参照してください。
例6-58 UPDATE文を使用したレコード変数への値の代入
この例では、従業員の給与をUPDATE
文で更新し、従業員の名前および新しい給与をレコード変数に戻します。
DECLARE TYPE EmpRec IS RECORD ( last_name employees.last_name%TYPE, salary employees.salary%TYPE ); emp_info EmpRec; old_salary employees.salary%TYPE; BEGIN SELECT salary INTO old_salary FROM employees WHERE employee_id = 100; UPDATE employees SET salary = salary * 1.1 WHERE employee_id = 100 RETURNING last_name, salary INTO emp_info; DBMS_OUTPUT.PUT_LINE ( 'Salary of ' || emp_info.last_name || ' raised from ' || old_salary || ' to ' || emp_info.salary ); END; /
結果:
Salary of King raised from 24000 to 26400
レコード変数へのNULLの代入
値NULL
をレコード変数に代入すると、その各フィールドに値NULL
が代入されます。
この代入は再帰的です(つまり、フィールドがレコードの場合は、それに属するフィールドにも値NULL
が代入されます)。
例6-59 レコード変数へのNULLの代入
この例では、レコード変数にNULL
を代入する前後に、レコード変数のフィールド(そのうちの1つがレコード)を出力します。
DECLARE
TYPE age_rec IS RECORD (
years INTEGER DEFAULT 35,
months INTEGER DEFAULT 6
);
TYPE name_rec IS RECORD (
first employees.first_name%TYPE DEFAULT 'John',
last employees.last_name%TYPE DEFAULT 'Doe',
age age_rec
);
name name_rec;
PROCEDURE print_name AS
BEGIN
DBMS_OUTPUT.PUT(NVL(name.first, 'NULL') || ' ');
DBMS_OUTPUT.PUT(NVL(name.last, 'NULL') || ', ');
DBMS_OUTPUT.PUT(NVL(TO_CHAR(name.age.years), 'NULL') || ' yrs ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(name.age.months), 'NULL') || ' mos');
END;
BEGIN
print_name;
name := NULL;
print_name;
END;
/
結果:
John Doe, 35 yrs 6 mos NULL NULL, NULL yrs NULL mos