--=======================
-- PL/SQL --> PL/SQL 記錄
--=======================
?
??? PL / SQL 記錄有著類似于表的數(shù)據(jù)結構,是一個或多個字段且擁有數(shù)據(jù)類型的集合體。定義了 PL / SQL 記錄類型之后,可以定義 PL / SQL 記錄變
量。聲明一個 PL / SQL 記錄變量相當于定義了多個標量變量,簡化了變量的聲明,從而大大節(jié)省了內存資源。多用于簡化單行多列的數(shù)據(jù)處理。
???
一、定義 PL / SQL 記錄
??? 1. 直接定義 PL / SQL 記錄 ( 首先定義記錄類型,類型中包含的記錄成員,其次是記錄類型變量 )
??????? TYPE type_name IS RECORD ????????????????????????????????????? --type_name 用于指定自定義記錄類型的名稱
??????? ( field_name1 datatype1 [NOT NULL] [ := DEFAULT EXPRESSION] , ?? -- 定義記錄的成員、數(shù)據(jù)類型及缺省值
??????? field_name2 datatype2 [NOT NULL] [ := DEFAULT EXPRESSION] ,
??????? ...
??????? field_nameN datatypeN [NOT NULL] [ := DEFAULT EXPRESSION] );
??????? record_name TYPE_NAME ; ????? ????????????????????????????????? -- 定義記錄變量名 record_name
??? 2. 使用 % rowtype 定義 PL / SQL 記錄
??????? 使用 % rowtype 時,記錄成員名稱和類型與所依賴對象 ( 表,視圖,游標 ) 名稱和類型完全相同
??????? 對于表和視圖,游標所有列定義時,使用 % rowtype 定義將大大節(jié)省內存空間
??????? record_name table_name % rowtype ????????????? -- 基于不同的對象定義 PL/SQL 記錄,此處為表
??????? record_name view_name % rowtype
??????? reocrd_name cursor_name % rowtype
?
二、 PL / SQL 記錄的使用
??? 1. SELECT INTO 語句中使用
??????? -- 使用 PL/SQL 記錄變量
??????????? undefine no
??????????? DECLARE
??????????????? TYPE emp_record_type IS RECORD
??????????????? (
??????????????????? name emp . ename % TYPE ,
??????????????????? salary emp . sal % TYPE ,
??????????????????? dno emp . deptno % TYPE
??????????????? );
??????????????? emp_record emp_record_type ;
??????????? BEGIN ????????????????????? -- 下面的查詢到的數(shù)據(jù)插入到記錄變量,注意列之間的順序與聲明順序保持一致
??????????????? SELECT ename , sal , deptno INTO emp_record ?
??????????????? FROM emp WHERE empno = & no ;
??????????????? dbms_output . put_line ( emp_record . name ); ?? -- 輸出時僅僅輸出記錄變量的一個成員 emp_record.name
??????????? END ; ???????????
???????????
??????????? Enter value for no : 7788
??????????? SCOTT
???????
??????? -- 使用 PL/SQL 記錄成員
??????????? undefine no
??????????? DECLARE
??????????????? TYPE emp_record_type IS RECORD
??????????????? (
??????????????????? name emp . ename % TYPE ,
??????????????????? salary emp . sal % TYPE ,
??????????????????? dno emp . deptno % TYPE
??????????????? );
??????????????? emp_record emp_record_type ;
??????????? BEGIN
??????????????? SELECT ename , sal INTO emp_record . name , emp_record . salary ? -- 此處僅僅使用到了 name 和 salary 成員
??????????????? FROM emp WHERE empno = & no ;
??????????? ??? dbms_output . put_line ( emp_record . name ); ?? -- 輸出時僅僅輸出記錄變量的一個成員 emp_record.name
??????????? END ;
??????????? / ??????????
???
??? 2. INSERT 語句中使用記錄變量及成員
??????? -- 使用 PL/SQL 記錄變量
??????????? DECLARE
??????????????? dept_record dept % ROWTYPE ;
??????????? BEGIN
??????????????? dept_record . deptno := 50 ;
??????????????? dept_record . dname := 'ADMINISTRATOR' ;
??? ??????????? dept_record . loc := 'BEIJING' ;
??????????????? INSERT INTO dept VALUES dept_record ;
??????????? END ;
??????????? / ??????
??????????? scott@ORCL > select * from dept where deptno = 50 ;
?
??????????????? DEPTNO DNAME ????????? LOC
??????????? ---------- -------------- -------------
??????????????????? 50 ADMINISTRATOR ? BEIJING ??????????
???????
??????? -- 使用 PL/SQL 記錄成員
??????????? scott@ORCL > DECLARE
??????????? ? 2 ? dept_record dept % ROWTYPE ;
??????????? ? 3 ? BEGIN
??????????? ? 4 ? dept_record . deptno := 60 ;
??????????? ? 5 ? dept_record . dname := 'SALES' ;
??????????? ? 6 ? INSERT INTO dept ( deptno , dname ) VALUES ( dept_record . deptno , dept_record . dname );
??????????? ? 7 ? END ;
??? ??????? ? 8 ? /
?
??????????? PL / SQL procedure successfully completed . ???
?
??????????? scott@ORCL > select * from dept where deptno in ( 50 , 60 );
?
??????????????? DEPTNO DNAME ????????? LOC
??????????? ---------- -------------- -------------
??????????????????? 50 ADMINISTRATOR ? BEIJING
??????????????????? 60 SALES ???????????????
???????
??? 3. UPDATE 語句中使用記錄變量及成員
??????? -- 使用 PL/SQL 記錄變量 ( 使用 ROW 來更新整行 )
??????????? DECLARE
??????????????? dept_record dept % ROWTYPE ;
??????????? BEGIN
??????????????? dept_record . deptno := 50 ;
??????????????? dept_record . dname := 'SERVICE' ;
??????????????? dept_record . loc := 'GuangZhou' ;
??????????????? UPDATE dept SET ROW = dept_record WHERE deptno = 50 ; -- 注意 update 時,使用 ROW 來表示整行
??????????? END ;
??????????? / ??????????????
???????
??????? -- 使用 PL/SQL 記錄成員 ( 使用成員記錄更新單列或多列 )
??????????? scott@ORCL > DECLARE
??????????? ? 2 ? dept_record dept % ROWTYPE ;
??????????? ? 3 ? BEGIN
??????????? ? 4 ????? dept_record . loc := 'ShangHai' ;
??????????? ? 5 ????? UPDATE dept SET loc = dept_record . loc WHERE deptno = 60 ;
??????????? ? 6 ? END ;
??????? ??? ? 7 ? / ?????????
???????
??? 4. DELETE 語句中使用記錄變量及成員
??????????? DECLARE
??????????????? dept_record dept % ROWTYPE ;
??????????? BEGIN
??????????????? dept_record . deptno := 60 ;
??????????????? DELETE FROM dept WHERE deptno = dept_record . deptno ;
??????????? END ;
??????????? / ??
???????
三、 PL / SQL 記錄使用時的幾個問題
??? 1. 記錄成員非空值的問題 ( 非空值應當在初始化時賦值,而不是在使用時賦值 )
??????? scott@ORCL > DECLARE
??????? ? 2 ? TYPE ex_type IS RECORD
??????? ? 3 ????? ( col1 NUMBER ( 3 ),
??????? ? 4 ?????? col2 VARCHAR2 ( 5 ) NOT NULL);
??????? ? 5 ? ex_record ex_type ;
??????? ? 6 ? BEGIN
??????? ? 7 ????? ex_record . col1 := 15 ;
??????????????? ? ex_record . col1 := TO_CHAR ( ex_record . col1 );
??????? ? 8 ????? ex_record . col2 := 'John' ;
??????? ? 9 ????? DBMS_OUTPUT . PUT_LINE ( 'ex_record.col1 is ' || ex_record . col1 );
??????? ? 10 ????? DBMS_OUTPUT . PUT_LINE ( 'ex_record.col2 is ' || ex_record . col2 );
??????? ? 11 ? END ;
??????? ? 12 ? /
??????????? ? col2 VARCHAR2 ( 5 ) NOT NULL);
??????????? ? *
??????? ERROR at line 4 :
??????? ORA - 06550 : line 4 , column 6 :
??????? PLS - 00218 : a variable declared NOT NULL must have an initialization assignment -- 錯誤消息指出非空值應當在初始化時指定
???????
??????? DECLARE
??????? ? TYPE ex_type IS RECORD (
??????????? col1 NUMBER ( 3 ),
??????????? col2 VARCHAR2 ( 5 ) NOT NULL := 'John' ); ? -- 注意對于非空值應當在初始化時賦值,而不是在使用時賦值
??????? ? ex_record ex_type ;
??????? BEGIN
??????? ? ex_record . col1 := 15 ;
??????? ? ex_record . col1 := TO_CHAR ( ex_record . col1 );
??????? ? --ex_record.col2:='John';
??????? ? DBMS_OUTPUT . PUT_LINE ( 'ex_record.col1 is ' || ex_record . col1 );
??????? ? DBMS_OUTPUT . PUT_LINE ( 'ex_record.col2 is ' || ex_record . col2 );
??????? END ;
???????
??????? ex_record . col1 is 15
??????? ex_record . col2 is John
???????
??? 2. 記錄變量之間的賦值問題
??????? 下面的例子中兩個 PL / SQL 變量 name_rec1 與 name_rec2 盡管具有表面上相同的定義,但兩者之間不能相互賦值
??????????? DECLARE
??????????? ? TYPE ex_type1 IS RECORD (
??????????????? first_name VARCHAR2 ( 15 ),
??????????????? last_name ? VARCHAR2 ( 30 ));
??????????? ? TYPE ex_type2 IS RECORD (
??????????????? first_name VARCHAR2 ( 15 ),
??????????????? last_name ? VARCHAR2 ( 30 ));
??????????? ? ex_rec1 ex_type1 ;
??????????? ? ex_rec2 ex_type2 ;
??????????? BEGIN
??????????? ? ex_rec1 . first_name := 'Robinson' ;
??????????? ? ex_rec1 . last_name ? := 'Cheng' ;
??????????? ? ex_rec2 ??????????? := ex_rec1 ; ? -- 不合理的賦值方式
??????????? END ; ???
???????
??????????? ? ex_rec2 ??????????? := ex_rec1 ;
??????????????????????????????????? *
??????????? ERROR at line 13 :
??????????? ORA - 06550 : line 13 , column 25 :
??????????? PLS - 00382 : expression is of wrong type
??????????? ORA - 06550 : line 13 , column 3 :
??????????? PL / SQL : Statement ignored
???????
??????? 具有相同的記錄類型時,不同記錄變量之間可以相互賦值
??????????? DECLARE
??????????? ? TYPE ex_type1 IS RECORD (
??????????????? first_name VARCHAR2 ( 15 ),
??????????????? last_name ? VARCHAR2 ( 30 ));
??????????? ? ex_rec1 ex_type1 ;
??????????? ? ex_rec2 ex_type1 ;
??????????? BEGIN
??????????? ? ex_rec1 . first_name := 'Robinson' ;
??????????? ? ex_rec1 . last_name ? := 'Cheng' ;
??????????? ? ex_rec2 ??????????? := ex_rec1 ;
??????????? ? DBMS_OUTPUT . PUT_LINE ( 'ex_rec1 is ' || ex_rec1 . first_name|| ' ' || ex_rec1 . last_name );
??????????? ? DBMS_OUTPUT . PUT_LINE ( 'ex_rec2 is ' || ex_rec2 . first_name|| ' ' || ex_rec2 . last_name );
??????????? END ; ???????
???????????
??????????? ex_rec1 is Robinson Cheng
??????????? ex_rec2 is Robinson Cheng
??? 3. 基于表,基于游標,基于自定義 PL / SQL 記錄的綜合使用
??????? DECLARE
??????? ? CURSOR dept_cur IS -- 聲明游標
??????????? SELECT * FROM dept WHERE deptno = 30 ;
??????? ? TYPE dept_type IS RECORD ( -- 聲明一個自定義的 PL/SQL 記錄類型
??????????? deptno NUMBER ( 2 ),
??????????? dname ? VARCHAR2 ( 14 ),
??????????? loc ??? VARCHAR2 ( 13 ));
?
??????? ? dept_rec1 dept % ROWTYPE ; -- 聲明基于表 dept 的記錄變量
??????? ? dept_rec2 dept_cur % ROWTYPE ; -- 聲明基于游標 dept_cur 的記錄變量
??????? ? dept_rec3 dept_type ; -- 聲明基于自定義 dept_type 的記錄變量
?
??????? BEGIN
??????? ? SELECT * INTO dept_rec1 FROM dept WHERE deptno = 30 ; -- 將查詢的結果插入到基于表 dept 的記錄變量中
?
??????? ? OPEN dept_cur ;
??????? ? LOOP
??????????? FETCH dept_cur
??????????? ? INTO dept_rec2 ; -- 將游標的內容插入到游標記錄變量中
??????????? EXIT WHEN dept_cur % NOTFOUND ;
??????? ? END LOOP ;
?
??????? ? dept_rec1 := dept_rec2 ;
??????? ? dept_rec3 := dept_rec2 ;
?
??????? ? DBMS_OUTPUT . PUT_LINE ( dept_rec1 . deptno || ' ' || dept_rec1 . dname );
??????? ? DBMS_OUTPUT . PUT_LINE ( dept_rec2 . deptno || ' ' || dept_rec2 . dname );
??????? ? DBMS_OUTPUT . PUT_LINE ( dept_rec3 . deptno || ' ' || dept_rec3 . dname );
??????? END ;
???????
??????? 30 SALES
??????? 30 SALES
??????? 30 SALES
???????????
四、更多參考
有關 SQL 請參考
??????? SQL 基礎--> 子查詢
??????? SQL 基礎--> 多表查詢
SQL 基礎--> ROLLUP 與CUBE 運算符實現(xiàn)數(shù)據(jù)匯總
SQL 基礎--> 層次化查詢(START BY ... CONNECT BY PRIOR)
?
??? 有關 PL/SQL 請參考
??????? PL/SQL --> 語言基礎
?
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
