1、 復合數據類型——記錄類型
? 語法格式
type 類型名 is record (
字段1 字段1類型 [not null]:=表達式1;
字段2 字段2類型 [not null] :=表達式2;
… )
? 說明:記錄之間相互賦值要求兩個記錄類型完全相同。
? 案例
舉例1
--創建表並插入記錄
create table student(idnumber, name varchar2(20), birthday date);
insert into studentvalues(100, 'xiaoming', to_date('2000.12.17', 'yyyy.mm.dd'));
insert into studentvalues(200, 'xiaohua', to_date('2001.12.17', 'yyyy.mm.dd'));
insert into studentvalues(300, 'xiaoli', to_date('2002.12.17', 'yyyy.mm.dd'));
--定義記錄類型
Declare
type t_studentRecord isrecord(
id number,
name varchar2(20),
birthday date);
或者:
type t_StudentRecord isrecord(
idstudent.id%type,
name student.name%type,
birthday student birthday%type);
v_students t_StudentRecord;
begin
select * into v_students from students whereid=200;
dbms_output.put_line(v_students.id||' '||v_students.name||' '||to_char(v_students.birthday,'yyyy-mm-dd'));
end;
舉例2
declare
type t_StudentRecord is record(
id number(4),
name varchar2(20),
birthday date);
v_students t_StudentRecord;
v_students_copy t_StudentRecord;
begin
v_students.id:=400;
v_students.name:='趙偉';
v_students.birthday:= to_date('2003.12.17','yyyy.mm.dd');
v_students_copy:=v_students;
dbms_output.put_line(v_students_copy.id||''||v_students_copy.name||' '|| to_char(v_students_copy. birthday, 'yyyy-mm-dd'));
end;
舉例3
declare
type t_StudentRecord is record(
id number(4),
name varchar2(20),
birthday date);
type t_StudentRecord2 is record(
id number(4),
namevarchar2(20),
birthday date);
v_students t_studentRecord;
v_students_copy t_studentRecord2;
begin
v_students.id:=400;
v_students.name:='趙偉';
v_students.birthday:= to_date('2003.12.17','yyyy.mm.dd');;
v_students_copy:=v_students;
dbms_output.put_line(v_students_copy.id||''||v_students_copy.name||' '|| to_char(v_students_copy. birthday, 'yyyy-mm-dd'));
end;
出錯說明:如果兩個記錄類型類型名不同,但是內容完全相同,兩個類型對應的兩個變量不能互相賦值。
2、 集合數據類型——index-by表
? 介紹:類似於普通程序設計語言中的數組概念。
? 聲明index-by表的方法:
Type 類型名 IS TABLE OF typeINDEX BY BINARY_INTEGER;
說明:其中type定義的是index-by表中各元素的類型,可以是內置類型、用戶定義的對象類型或者使用%rowtype的表達式等。
? index-by表中單個元素
在聲明了類型和變量後,可以通過:變量名(index)使用表中的單個元素,其中index是指表中的第幾個元素。
? Index by表的屬性函數
屬性名稱
數據類型
說 明
count
number
返回表中的行數
delete
無
用於從表中刪除指定(由傳入參數指定)的一行數據
exists
boolean
如果指定的行存在則返回true,否則返回false
first
binary_integer
返回表中第一行的下標
last
binary_integer
返回表中最後一行的下標
next
binary_integer
返回指定行(由傳入參數指定)的下一行的下標
prior
binary_integer
在指定行(由傳入參數指定)的上一行的下標
? 案例
舉例1
declare
type t_StudentRecord isrecord(
idstudent.id%type,
name student.name%type,
birthdaystudent birthday%type);
type t_studentTable is table oft_StudentRecord index by binary_integer;
v_students t_studentTable;
begin:
select * into v_students(100) from student whereid=100;
dbms_output.put_line(v_students(100).id||''||v_students(100).name||' '|| to_char(v_students(100). birthday, 'yyyy-mm-dd'));
end;
舉例2
declare
type t_studentTable is table of student%rowtypeindex by binary_integer;
v_students t_studentTable;
begin
select * into v_students(1) from student whereid=200;
dbms_output.put_line(v_students(1).id ||''||v_students(1).name||'
'|| to_char(v_students(1). birthday,'yyyy-mm-dd'));
end;
舉例3
Declare
Type t_s is table of scott.emp%rowtype Indexby binary_integer;
V_s t_s;
V_index binary_integer;--索引號
V_loop binary_integer;--循環次數
Begin
Select * into v_s(10) from scott.emp whereempno='7788';
Select * into v_s(22) fromscott.emp where empno='7902';
Select * into v_s(-12) fromscott.emp where empno='7934';
V_index:= v_s.first;
V_loop:=v_s.count;
Loop
Dbms_output.put_line(v_s(v_index).empno);
V_index:=v_s.next(v_index);
V_loop:=v_loop-1;
Exit when v_loop<=0;
End loop;
V_index:=v_s.last;
v_s.delete(v_index);
V_index:= v_s.first;
V_loop:=v_s.count;
Loop
Dbms_output.put_line(v_s(v_index).empno);
V_index:=v_s.next(v_index);
V_loop:=v_loop-1;
Exit when v_loop<=0;
End loop;
End;
3、 集合數據類型——變長數組
? 介紹:變長數組:是一個存儲有序元素的集合,每個元素都有一個索引,該索引相對應元素在數組中的位置。變長數組存在大小的限制,但是可以動態進行更改。
? 創建變長數組語句:
? 案例
--創建一個變長數組
Create Type varray_phone as varray(3) of varchar2(50);
--創建一個人員表,表中人員擁有一列電話(可能有1、2或3個電話號碼)。
create table person3
(
id integer constraintperson3_pk primary key,
first_name varchar(20),
last_name varchar(20),
phone varray_phone
)
--填充變長數組
insert into person3values(1,'yuan','weixiang',varray_phone('12345','34567','56789'));
select * from person3;
insert intoperson3 values(2,'hao','lihai',varray_phone());
select * from person3;
--修改變長數組中的元素
update person3 setphone= varray_phone('12345','34567') where id = 2;
select * from person3;
--修改變長數組的元素的長度大小
Alter type varray_phone modifyelement type varchar2(49) cascade --報錯
Alter type varray_phone modify element type varchar2(60)cascade
說明:cascade選項把更改傳播到數據庫中的依賴對象 Person3就是依賴對象
--修改變長數組元素的數目
alter type varray_phonemodify limit 2 cascade -- 報錯,varray限制只能增大
alter type varray_phonemodify limit 5 cascade
insert into person3 values(3,'yuan','weixiang',varray_phone('12345','34567','56789','34567','56789'));
4、 游標
? 介紹:在PL/SQL程序設計中,有時需要對查詢返回結果集進行逐行處理,這就需要將該查詢返回結果集緩存到一個內存區中,為了能對返回的結果集進行逐行操作,需返回該內存區的首地址,這個地址被稱為游標。
? 定義游標語法
Cursor 游標名 is select語句;
注意:在游標定義中的select語句不能包含into子句。
? 游標屬性
游標屬性
描 述
游標名%isopen
布爾值,如果游標已打開,取值為true,否則為false。
游標名%notfound
布爾值,如果最近一次fetch操作沒有返回結果,則取值為true,否則為false。
游標名%found
布爾值,如果最近一次fetch操作沒有返回結果,則取值為false,否則為true。
游標名%rowcount
數字型值,值為到當前為止返回的行數。
? 案例
舉例1
DECLARE
v_no scott.emp.empno%type;
v_name scott.emp.ename%type;
CURSORc_e IS SELECT empno, ename FROM scott.emp;
BEGIN
OPEN c_e;
LOOP
FETCH c_e INTO v_no, v_name;
EXIT WHEN c_e%NOTFOUND;
Dbms_output.put_lint(v_no||' '||v_name);
END LOOP;
CLOSE c_e;
END;
舉例2
DECLARE
CURSOR c_e IS SELECT empno, ename FROM scott.emp;
BEGIN
For c1 in c_e loop
Dbms_output.put_lint(c1.empno||' '||c1.ename);
END LOOP;
END;
5、 可更新的游標
? 介紹:從游標中抽取數據,可以對數據庫中的數據進行update和delete操作。
? 語法:在定義游標時,必須加for update of子句;在update和delete語句中加上where current of子句。
? 案例
舉例1:對scott方案emp表中某部門的各員工,如果其工資小於1600元,則將其工資設為1600元。
Accept p_deptno prompt‘please enter the deptno’;
--Accept類似與c語言中的scanf,意為從屏幕接受輸入到p_deptno變量中。
declare
v_deptno scott.emp.deptno%type:=&p_deptno;
cursor emp_cursor is select empno,job,sal from scott.emp wheredeptno=v_deptno for update of sal;
begin
for emp_record in emp_cursor loop
if emp_record.sal<1600 then
update emp set sal=1600 where currentof emp_cursor;
end if;
end loop;
end;
舉例2:為職工漲工資,對員工按工資從低到高排序,從工資低的員工開始漲,每位員工漲10%。但要控制員工總工資在50萬之內,一旦總額超過50萬,就停止對剩余的員工漲工資。
6、 帶參數的游標
? 介紹:定義顯示游標時,可以加入參數的定義。在使用游標時,對於參數輸入不同的數值,則游標緩存中的數據也隨之變化。
? 定義游標語法:
cursor 游標名(參數1 數據類型, ….) is select 子句;
? 打開游標語法:
open游標名(&參數1, ….) ;
? 案例:從scott方案的emp表中查詢並打印某個部門的雇員情況,其中部門號由用戶交互式輸入。
Accept v_deptnoprompt‘please enter the deptno;
declare
v_ename scott.emp.ename%type;
v_sal scott.emp.sal%type;
cursor emp_cursor (v_deptno number) is selectename,sal from scott.emp where deptno=v_deptno;
begin
open emp_cursor(&p_deptno);
loop
fetch emp_cursor into v_ename,v_sal;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename|| ' '||v_sal);
end loop;
close emp_cursor;
end;