记录类型是把逻辑相关的数据作为一个单元存储起来,它必须包括至少一个标量型或 RECORD 数据类型的成员,称作 PL RECORD 的域(FIELD),其作用是存放互不相同但逻辑相关的信息。记录的内部组件称为字段,访问记录的字段时,需要使用符号“.”,格式为:记录名**.**字段名。
创建记录
创建记录有以下三种方式:
声明一个 RECORD 类型,然后声明一个该类型的变量。语法如下:
TYPE record_name IS RECORD
( field_name data_type [:= initial_value]
[, field_name data_type [:= initial_value ] ]... );
variable_name record_name;
声明一个变量,类型跟一个表的行类型关联。语法如下:
variable_name table_name%ROWTYPE ;
说明
记录的字段跟表的列名字和数据类型一一对应。
声明一个变量,类型跟一个游标的类型关联。语法如下:
variable_name cursor_name%ROWTYPE ;
说明
记录的字段跟游标的 SELECT 查询里的列的名字和数据类型一一对应。
示例如下:
obclient> set serveroutput on;
Query OK, 0 rows affected (0.00 sec)
obclient> DECLARE
-> TYPE T_my_rec IS RECORD(
-> Code VARCHAR2(10),
-> Name VARCHAR2(50) NOT NULL :='book');
-> V_book T_my_rec;
-> BEGIN
-> V_book.code :='10000';
-> V_book.name :='OceanBase PL Developer Guide';
-> DBMS_OUTPUT.PUT_LINE(v_book.code||': '||v_book.name);
-> END;
-> /
Query OK, 0 rows affected (0.04 sec)
10000: OceanBase PL Developer Guide
注意
对记录变量的操作和普通变量相同, 可以用 SELECT 语句对其进行赋值
声明记录类型
声明记录类型时,字段的类型可以使用 STORED PROCEDURE 支持的数据类型,或者使用 %TYPE 方法复制表或者游标的列的类型。
示例如下:
delimiter /
CREATE OR REPLACE PACKAGE pkg_ware_mgmt as
TYPE TYPE_WARE IS RECORD(
w_id ware.w_id%TYPE
,w_ytd ware.w_ytd%TYPE
,w_tax ware.w_tax%TYPE
,w_name ware.w_name%TYPE
,w_street_1 ware.w_street_1%TYPE
,w_street_2 ware.w_street_2%TYPE
,w_city ware.w_city%TYPE
,w_state ware.w_state%TYPE
,w_zip ware.w_zip%TYPE
);
END;
/
delimiter ;
利用记录插入和更新表
PL 程序允许用户利用记录的值插入记录,或者更新表中的记录。 要求记录中元素的数量和类型能够表示一个完整的行。 更新记录时,利用伪列 ROW 代表匹配到的行。如下例所示:
obclient> select * from regions;
+-----------+------------------------+
| REGION_ID | REGION_NAME |
+-----------+------------------------+
| 1 | Europe |
| 2 | Americas |
| 3 | Asia |
| 4 | Middle East and Africa |
+-----------+------------------------+
4 rows in set (0.00 sec)
obclient> DECLARE
-> TYPE region_record_type IS RECORD (
-> id REGIONS.region_id%TYPE,
-> name REGIONS.region_name%TYPE
-> );
-> region_record region_record_type;
-> BEGIN
-> region_record.id := 5;
-> region_record.name := 'Antarctica';
-> insert into REGIONS values region_record;
-> region_record.id := 3;
-> region_record.name := 'Asia Update';
-> update REGIONS set ROW = region_record
-> where REGION_ID = region_record.id;
-> end;
-> /
Query OK, 0 rows affected (0.05 sec)
obclient> select * from regions;
+-----------+------------------------+
| REGION_ID | REGION_NAME |
+-----------+------------------------+
| 1 | Europe |
| 2 | Americas |
| 3 | Asia Update |
| 4 | Middle East and Africa |
| 5 | Antarctica |
+-----------+------------------------+
创建和调用带记录类型参数的子程序
记录类型的变量跟其他常用数据类型的变量一样可以作为参数传递给子程序。
示例:创建和调用带记录类型参数的子程序
下面示例用两种方式定义了记录类型的变量:
r_ware1 TYPE_WARE;
r_ware2 ware%ROWTYPE;
然后通过 SELECT INTO 语句演示了给记录变量赋值的两种方法。由于这两个变量的类型实际结构是相同的,所以两个变量可以进行赋值操作:r_ware1 := r_ware2;
最后将记录变量作为参数传递给子程序打印变量的值。
delimiter /
CREATE OR REPLACE PACKAGE pkg_ware_mgmt as
TYPE TYPE_WARE IS RECORD(
w_id ware.w_id%TYPE
,w_ytd ware.w_ytd%TYPE
,w_tax ware.w_tax%TYPE
,w_name ware.w_name%TYPE
,w_street_1 ware.w_street_1%TYPE
,w_street_2 ware.w_street_2%TYPE
,w_city ware.w_city%TYPE
,w_state ware.w_state%TYPE
,w_zip ware.w_zip%TYPE
);
PROCEDURE sp_record_print(p_w_id IN ware.w_id%type);
END;
/
delimiter ;
delimiter /
CREATE OR REPLACE PACKAGE BODY pkg_ware_mgmt
AS
PROCEDURE sp_record_print_by_record(p_record IN TYPE_WARE)
AS
BEGIN
dbms_output.put_line('Print a record :');
dbms_output.put_line('W_ID : ' || p_record.w_id
|| ', W_YTD : ' || p_record.w_ytd
|| ', W_TAX : ' || p_record.w_tax
|| ', W_NAME : ' || p_record.w_name
|| ', W_STREET_1 : ' || p_record.w_street_1
|| ', W_STREET_2 : ' || p_record.w_street_2
|| ', W_CITY : ' || p_record.w_city
|| ', W_STATE : ' || p_record.w_state
|| ', W_ZIP : ' || p_record.w_zip )
;
dbms_output.put_line('');
END;
PROCEDURE sp_record_print(p_w_id IN ware.w_id%TYPE )
IS
r_ware1 TYPE_WARE;
r_ware2 ware%ROWTYPE;
BEGIN
SELECT "W_ID","W_YTD","W_TAX","W_NAME","W_STREET_1","W_STREET_2","W_CITY","W_STATE","W_ZIP"
INTO r_ware1.w_id, r_ware1.w_ytd, r_ware1.w_tax, r_ware1.w_name, r_ware1.w_street_1, r_ware1.w_street_2, r_ware1.w_city, r_ware1.w_state, r_ware1.w_zip
FROM ware
WHERE w_id = p_w_id;
sp_record_print_by_record(r_ware1);
SELECT "W_ID","W_YTD","W_TAX","W_NAME","W_STREET_1","W_STREET_2","W_CITY","W_STATE","W_ZIP"
INTO r_ware2
FROM ware
WHERE w_id = p_w_id + 1;
r_ware1 := r_ware2;
sp_record_print_by_record(r_ware1);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Raise an unkown exception !');
END ;
END;
/
delimiter ;
obclient> call pkg_ware_mgmt.sp_record_print(1);
Query OK, 0 rows affected (0.12 sec)
Print a record :
W_ID : 1, W_YTD : 1200, W_TAX : .1868, W_NAME : W_NAME_1, W_STREET_1 : jTNkXKWXOdh, W_STREET_2 : lf9QXTXXGoF04IZBkCP7, W_CITY : srRq15uvxe5, W_STATE : GQ, W_ZIP : 506811111
Print a record :
W_ID : 2, W_YTD : 1200, W_TAX : .0862, W_NAME : W_NAME_2, W_STREET_1 : xEdT1jkENtbLwoI1Zb0, W_STREET_2 : NT0j4RCQ4OqrS, W_CITY : vlwzndw2FPrO, W_STATE : XR, W_ZIP : 063311111
obclient>