Oracle Record Variables(Oracle记录变量)是Oracle数据库编程中PL/SQL语言的一个关键特性,它允许开发者将多个相关的、分离的、基本数据类型的变量组合成一个复合数据类型,类似于C语言中的结构体(STRUCTURE)。这种复合数据类型被称为RECORD(记录)。在PL/SQL中,记录变量提供了一种非常灵活和强大的方式来处理来自数据库的行数据。
记录变量Record Variables
您可以通过以下任何一种方式创建记录变量:
- 定义一个RECORD类型,然后声明该类型的变量。
- 使用%ROWTYPE声明一个记录变量,该变量表示数据库表或视图的完整行或部分行。
- 使用%TYPE声明与之前声明的记录变量类型相同的记录变量。
有关语法和语义,请参阅"记录变量声明"。
Topics 话题
- 记录变量的初始值
- 声明记录常量
- 记录类型
- 使用%ROWTYPE属性声明项目
一、Oracle Record Variables的概念
Oracle Record Variables定义了一种记录数据类型,允许将多个字段(每个字段都有其数据类型)组合成一个单一的数据结构。这种数据结构可以被用来存储或处理数据库中的一行数据。使用记录变量时,需要在声明部分先定义记录的组成(即记录中包含哪些字段以及每个字段的数据类型),然后声明一个或多个该记录类型的变量,并在执行部分引用这些记录变量本身或其中的成员。
二、Oracle Record Variables的语法
Oracle Record Variables的声明和定义遵循以下基本语法:
sql
TYPE RECORD_NAME IS RECORD (
FIELD1 DATA_TYPE1 [NOT NULL] [:= DEFAULT_VALUE],
FIELD2 DATA_TYPE2 [NOT NULL] [:= DEFAULT_VALUE],
...
FIELDN DATA_TYPEN [NOT NULL] [:= DEFAULT_VALUE]
);
VARIABLE_NAME RECORD_NAME;
- RECORD_NAME 是你定义的记录类型的名称。
- FIELD1 到 FIELDN 是记录中包含的字段名。
- DATA_TYPE1 到 DATA_TYPEN 是每个字段对应的数据类型。
- [NOT NULL] 和 [:= DEFAULT_VALUE] 是可选的,用于指定字段是否可以为空以及默认值。
- VARIABLE_NAME 是你声明的记录类型变量的名称。
三、Oracle Record Variables的使用
在使用记录变量时,你可以通过.运算符来访问记录中的字段。记录变量常用于存储从数据库中查询出的单行数据,或者作为过程、函数等的参数来传递复杂的数据结构。
3.1、声明记录常量Declaring Record Constant
sql
DECLARE
TYPE My_Rec IS RECORD (a NUMBER, b NUMBER);
r CONSTANT My_Rec := My_Rec(0,1);
BEGIN
DBMS_OUTPUT.PUT_LINE('r.a = ' || r.a);
DBMS_OUTPUT.PUT_LINE('r.b = ' || r.b);
END;
/
在Oracle Database Release 18c之前,为了实现相同的结果,您必须使用一个函数声明一个记录常量,该函数用其初始值填充记录,然后在常量声明中调用该函数。通过比较这两个示例,您可以观察到,限定表达式通过更简洁的方式提高了程序的清晰度和开发人员的生产力。
sql
CREATE OR REPLACE PACKAGE My_Types AUTHID CURRENT_USER IS
TYPE My_Rec IS RECORD (a NUMBER, b NUMBER);
FUNCTION Init_My_Rec RETURN My_Rec;
END My_Types;
/
CREATE OR REPLACE PACKAGE BODY My_Types IS
FUNCTION Init_My_Rec RETURN My_Rec IS
Rec My_Rec;
BEGIN
Rec.a := 0;
Rec.b := 1;
RETURN Rec;
END Init_My_Rec;
END My_Types;
/
sql
HR@orcl> set serveroutput on
HR@orcl> DECLARE
2 r CONSTANT My_Types.My_Rec := My_Types.Init_My_Rec();
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE('r.a = ' || r.a);
5 DBMS_OUTPUT.PUT_LINE('r.b = ' || r.b);
6 END;
7 /
r.a = 0
r.b = 1
PL/SQL procedure successfully completed.
此示例显示了使用位置表示法用限定表达式初始化的记录常数c_small。c_road记录常量使用命名关联符号用限定表达式初始化。
sql
DECLARE
TYPE t_size IS RECORD (x NUMBER, y NUMBER);
c_small CONSTANT t_size := t_size(32,36);
c_large CONSTANT t_size := t_size(x => 192, y => 292);
BEGIN
DBMS_OUTPUT.PUT_LINE('Small size is ' || c_small.x || ' by ' || c_small.y);
DBMS_OUTPUT.PUT_LINE('Large size is ' || c_large.x || ' by ' || c_large.y);
END;
/
Small size is 32 by 36
Large size is 192 by 292
PL/SQL procedure successfully completed.
3.2、记录类型定义和变量声明
此示例定义了一个名为DeptRecTyp的RECORD类型,为每个字段指定一个初始值。然后,它声明了一个名为dept_rec的该类型变量,并打印其字段。
sql
DECLARE
TYPE DeptRecTyp IS RECORD (
dept_id NUMBER(4) NOT NULL := 10,
dept_name VARCHAR2(30) NOT NULL := 'Administration',
mgr_id NUMBER(6) := 200,
loc_id NUMBER(4) := 1700
);
dept_rec DeptRecTyp;
BEGIN
DBMS_OUTPUT.PUT_LINE('dept_id: ' || dept_rec.dept_id);
DBMS_OUTPUT.PUT_LINE('dept_name: ' || dept_rec.dept_name);
DBMS_OUTPUT.PUT_LINE('mgr_id: ' || dept_rec.mgr_id);
DBMS_OUTPUT.PUT_LINE('loc_id: ' || dept_rec.loc_id);
END;
/
3.3、带记录字段的记录类型(嵌套记录)
此示例定义了两种RECORD类型,name_rec和contact。类型contact有一个name_rec类型的字段。
sql
DECLARE
TYPE name_rec IS RECORD (
first employees.first_name%TYPE,
last employees.last_name%TYPE
);
TYPE contact IS RECORD (
name name_rec, -- nested record
phone employees.phone_number%TYPE
);
friend contact;
BEGIN
friend.name.first := 'John';
friend.name.last := 'Smith';
friend.phone := '1-650-555-1234';
DBMS_OUTPUT.PUT_LINE (
friend.name.first || ' ' ||
friend.name.last || ', ' ||
friend.phone
);
END;
/
3.4、带Varra动态数组类型的记录类型
这定义了一个VARRAY类型full_name和一个RECORD类型contact。类型contact的一个name字段类型为full_name。
This defines a VARRAY type, full_name, and a RECORD type, contact. The type contact has a field of type full_name.
sql
DECLARE
TYPE full_name IS VARRAY(2) OF VARCHAR2(20);
TYPE contact IS RECORD (
name full_name := full_name('John', 'Smith'), -- varray field
phone employees.phone_number%TYPE
);
friend contact;
BEGIN
friend.phone := '1-650-555-1234';
DBMS_OUTPUT.PUT_LINE (
friend.name(1) || ' ' ||
friend.name(2) || ', ' ||
friend.phone
);
END;
/
3.5、相同定义的包和本地记录类型
在这个例子中,包pkg和匿名块对RECORD类型rec_type的定义是相同的。该包定义了一个过程print_rec_type,它有一个rec_type参数。匿名块声明包类型的变量r1(pkg.rec_type)和本地类型的变量r2(rec_type)。匿名块可以将r1传递给print_rec_type,但不能将r2传递给print-rec_type。
sql
CREATE OR REPLACE PACKAGE pkg AS
TYPE rec_type IS RECORD ( -- package RECORD type
f1 INTEGER,
f2 VARCHAR2(4)
);
PROCEDURE print_rec_type (rec rec_type);
END pkg;
/
CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE print_rec_type (rec rec_type) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(rec.f1);
DBMS_OUTPUT.PUT_LINE(rec.f2);
END;
END pkg;
/
包pkg和匿名块调用
sql
DECLARE
TYPE rec_type IS RECORD ( -- local RECORD type
f1 INTEGER,
f2 VARCHAR2(4)
);
r1 pkg.rec_type; -- package type
r2 rec_type; -- local type
BEGIN
r1.f1 := 10; r1.f2 := 'abcd';
r2.f1 := 25; r2.f2 := 'wxyz';
pkg.print_rec_type(r1); -- succeeds
pkg.print_rec_type(r2); -- fails
END;
/
四、总结
Oracle Record Variables提供了一种灵活且强大的方式来处理数据库中的行数据。通过定义记录类型并声明记录变量,开发者可以方便地存储、处理和传递复杂的数据结构。记录变量在PL/SQL编程中扮演着至关重要的角色,是Oracle数据库编程不可或缺的一部分。