
exception
异常处理
end
exception
异常处理
end;
第一类 :PL/SQL 变量
(DECLARE 阶段别声明和初始化)
(每一行只声明一个变量)
(在执行阶段被赋予新值)
(可以在PL/SQL之间传递)
(通过标准输出包可以看到结果)
表汇总的字段数据类型
varchar2 4000
char 2000
long 2G


SQL> declare
2 v_1 number;
3 v_2 number(2);
4 v_3 int;
5 v_4 varchar2(20) default 'abc';
6 v_5 constant varchar2(20) :='zyx';
7 v_6 number not null :=120;
8 v_7 boolean :=false;
9 v_8 rowid;
10 begin
11 null;
12 v_1:=1.232434;
13 v_1 :=200;
14 end;
15 /
PL/SQL 过程已成功完成。
SQL>


SQL> ed
已写入 file afiedt.buf
1 declare
2 empno number;
3 v_2 number(2);
4 v_3 int;
5 v_4 varchar2(20) default 'abc';
6 v_5 constant varchar2(20) :='zyx';
7 v_6 number not null :=120;
8 v_7 boolean :=false;
9 v_8 rowid;
10 begin
11 null;
12 empno:=7788;
13 delete emp where empno=empno;
14* end;
SQL> /
PL/SQL 过程已成功完成。
SQL> select * from emp;
未选定行

SQLPLUS 或者「命令窗口」中如果没有输出,可以使用 set serveroutp on 来修改 是否能输出
ed
已写入 file afiedt.buf
1 declare
2 empno number;
3 v_2 number(2);
4 v_3 int;
5 v_4 varchar2(20) default 'abc';
6 v_5 constant varchar2(20) :='zyx';
7 v_6 number not null :=120;
8 v_7 boolean :=false;
9 v_8 rowid;
10 begin
11 null;
12 empno :=7788;
13 v_2:=1;
14 dbms_output.put_line('变量v2的值是:'|| v_2); 这里也可以写sysdate
15* end;
SQL> /
变量v2的值是:1
PL/SQL 过程已成功完成。

也可以缓存v_4 v_5

已写入 file afiedt.buf
1 declare
2 v_var1 number:=123;
3 begin
4 dbms_output.put_line('OUT:v_var1:'||v_var1);
5 declare
6 v_var2 number:=456;
7 begin
8 dbms_output.put_line('IN:v_var1:'||v_var1);
9 dbms_output.put_line('IN:v_var2:'||v_var2);
10 END;
11 --dbms_output.put_line('IN:v_var2:'||v_var2); 内部中的变量不能被外部块使用,去掉注释就报错
12* end;
SQL> /
OUT:v_var1:123
IN:v_var1:123
IN:v_var2:456
PL/SQL 过程已成功完成。
外部的变量可以内部使用,但是内部的变量外部不能使用
SQL> ed
已写入 file afiedt.buf
1 declare
2 v_out varchar2(20) :='this is out';
3 begin
4 dbms_output.put_line(v_out);
5 declare
6 v_inner varchar2(20) :='this is inner';
7 begin
8 v_out:='abc'; --这里还可以重新赋值
9 dbms_output.put_line(v_out);
10 dbms_output.put_line(v_inner);
11 end;
12* end;
SQL> /
this is out
abc
this is inner
PL/SQL 过程已成功完成。
语句库的标签可以加在一个语句块开始的位置上 当外部块和内部块出现同命名变量时 借助标签 来区别 但是这样的程序可读性太差 尽量不要使用变量名来重复

在PL sql 里面嵌入 sql 语句 使用SELECT 查询结果对变量赋值
PL/SQL 中的select 必须使用into 将选出结果存入变量之内
SQL> ed
已写入 file afiedt.buf
1 declare
2 v_sal number ;
3 v_job varchar2(20);
4 begin
5 select sal , job into v_sal,v_job from emp where empno=7788;
6 dbms_output.put_line(v_sal||','||v_job);
7* end;
SQL> /
3000,ANALYST
PL/SQL 过程已成功完成。
使用 %type 参照方式定义变量的类型
有时在程序中声明的变量 很多时候是为了存放表中的列数据 这样我们自己定义变量类型时往往都是和表中的类型以及长度一致的 %type 就可以避免复杂的输入 直接可以参照表的某列的类型直接作为变量的类型这样即使表中的类型被修改了 程序中的类型也随之改变 程序的健壮性提高
SQL> declare
2 v_ename scott.emp.ename%type;
3 begin
4 select ename into v_ename from scott.emp where empno=7788;
5 dbms_output.put_line(v_ename);
6 end;
7 /
SCOTT
PL/SQL 过程已成功完成。
2 复合变量
记录 (record)
使用方法
1 先定义类型,类型中国描述了这是一个 RECORD
2 但却没有 说明内部 具体列的内容
定义自定义 类型就是为了 定义 record 内部 包含什么列
3 在将定义好的类型 关联一个变量
引用 record 类型中的值 记录名 内部列名
declare
2 type rec_typ is record(
3 v_ename emp.ename%type,
4 v_job emp.job%type,
5 v_sal emp.sal%type);
6
7 v_rec rec_typ;
8 begin
9 select ename,job,sal into v_rec.v_ename,v_rec.v_job,v_rec.v_sal from emp where
10 empno=&no;
11 dbms_output.put_line(
12 'his name is'||v_rec.v_ename||','||chr(10)||
13 'his job is'||v_rec.v_job||','||chr(10)||
14 'his name is'||v_rec.v_sal||','
15 );
16 end;
17 /
输入 no 的值: 7788
原值 10: empno=&no;
新值 10: empno=7788;
his name isSCOTT,
his job isANALYST,
his name is3000,
PL/SQL 过程已成功完成。



使用8个变量在一行
使用 %rowtype 来代替 record 的类型定义
和 %type 类型 %type是参照一列的类型
而 %rowtype 是将表的所有列做为了record中的成员
列名即是成员名

此时当然也可以使用 加入sal job ename

PL/SQL 表 (INDEX BY 表)
类似于属组,但下标除了定义成数字外还可以定义为字符,定义成数值下标时必须要使用
binary_integer 类型 binary_integer 类型相比 number 类型区别 :
存储的数据以二进制方式存储 占用更少的空间
可以存储 -2147483747- 2147483747 之间的任意整数
主要使用在PL/SQL 表的下标类型撒花姑娘不能出现在常规的类型上反之 PL/SQL 表的下标也不能使用number 来取代
使用方法
1 先定义类型,指出下面是数字还是字符
2 在类型关联变量
引用 PL/SQL 表中的元素 :表名 (下标)
SQL> ed
已写入 file afiedt.buf
1 declare
2 type tab_typ is table of varchar2(20) index by binary_integer ;
3 v_tab tab_typ;
4 begin
5 v_tab(1):='jason';
6 v_tab(2):='jack';
7 select ename into v_tab(3) from emp where empno=7788;
8 dbms_output.put_line(v_tab(1)||',' ||v_tab(2)||','||v_tab(3));
9* end;
SQL> /
jason,jack,SCOTT
PL/SQL 过程已成功完成。
也可以修改里面的 变量值

SQL> ed
已写入 file afiedt.buf
1 declare
2 type tab_typ is table of varchar2(20) index by varchar2(1);
3 v_tab tab_typ;
4 begin
5 v_tab('a'):='jason';
6 v_tab('b'):='jack';
7 select ename into v_tab('c') from emp where empno=7788;
8 dbms_output.put_line(v_tab('a')||',' ||v_tab('b')||','||v_tab('c'));
9 dbms_output.put_line(v_tab.first);
10 dbms_output.put_line(v_tab.last);
11 dbms_output.put_line(v_tab.prior('b'));
12 /*
13 前一个下标
14 */
15 dbms_output.put_line(v_tab.next('b'));
16 /*
17 b 的下一个下标
18 */
19 dbms_output.put_line(v_tab.count);
20* end;
PL/SQL 表的缺陷是:
of 类型的定义比较死板
定义的类型是字符 所有值就只能存储字符
定义的累累是数字 所有值就只能存储数字
解决办法是使用PL/SQL 表+ record 可以随心所欲的存不同类型值
PL/SQL 表+record
PL/SQL 中不能直接使用select 需要使用 select into 将查询结果插入到标量在
dms_output打印标量
1 先定义record 类型,声明类型中包含哪些列
2 在定义PL/SQL 类型 PL/SQL 表类型关联之前定义的record 类型
3 这样就将 record 作为了PL/SQL 表中的元素
4 在将PL/SQL 类型关联到变量中
引用方法 :
赋值 :PL/SQL 表名 下标
取值: PL/SQL 表名(下标).record 的列名
SQL> ed
已写入 file afiedt.buf
1 declare
2 type rec_typ is record(
3 v_ename varchar2(20),
4 v_sal number);
5 type tab_typ is table of rec_typ index by binary_integer;
6 /*
7 默认为整形
8 */
9 v_tab tab_typ;
10 begin
11 v_tab(1).v_ename:='jack';
12 v_tab(1).v_sal:=3000;
13 select ename,sal into v_tab(2).v_ename,v_tab(2).v_sal
14 from emp where empno=7788;
15 dbms_output.put_line(v_tab(1).v_ename|| chr(10)||
16 v_tab(1).v_sal|| chr(10)||
17 v_tab(2).v_ename|| chr(10)||
18 v_tab(2).v_sal);
19* end;
SQL> /
jack
3000
SCOTT
3000
PL/SQL 过程已成功完成。
当然此时我们也可以简写

在sqlplus的外部声明一下
SQL> var x varchar2(100);
SQL> begin
2 :x:='tttt';
3 end;
4 /
PL/SQL 过程已成功完成。
SQL> print x
X
--------------------------------------------------------------------------------
tttt 这可以操作
SQL> begin
2 select ename into :x from emp where empno=7839;
3 end;
4 /
PL/SQL 过程已成功完成。
SQL> print x
X
--------------------------------------------------------------------------------
KING
使用 IF语句按条件判断,控制PL/SQL 流程 ;
if -then -end if
if- then-else-end if
if-then-elsif-then-else-end if
Oracle 的写法
if expr1
then
action1
elif expr2
then
action2
else
default_action;
fi
if
expr1
then
action1;
elsif expr2;
then action2 ;
...
else
default action;
end if;
set serveroutput on 打开后台显示
开始声明
SQL> ed
已写入 file afiedt.buf
1 declare
2 v_hour number :=(to_char(sysdate,'hh24'));
3 begin
4 if v_hour >=6 and v_hour<=11 then
5 dbms_output.put_line('现在是上午');
6 else
7 dbms_output.put_line('现在不是上午');
8 end if;
9* end;
SQL> /
现在不是上午
PL/SQL 过程已成功完成。 单分支情况

我们还可以继续嵌套

使用 CASE 分支
1 declare
2 v_grade varchar2(1) :=upper('&grade');
3 v_info varchar2(20);
4 begin
5 v_info:=
6 case v_grade when 'A' then
7 'excellent'
8 when 'B' then
9 'very good!!!'
10 when 'C' then
11 'yiban'
12 else 'No such as grade!!!'
13 end;
14 dbms_output.put_line(
15 'the grade is'|| v_grade||chr(10)||
16 ' the information is ' || v_info
17 );
18* end;
SQL> /
输入 grade 的值: C
原值 2: v_grade varchar2(1) :=upper('&grade');
新值 2: v_grade varchar2(1) :=upper('C');
the grade isC
the information is yiban
PL/SQL 过程已成功完成。
使用别的分支函数
SQL> ed
已写入 file afiedt.buf
1 declare
2 v_grade varchar2(1) :=upper('&grade');
3 v_info varchar2(20);
4 begin
5 case
6 when
7 v_grade = 'A' then
8 v_info:='excellent!!!!';
9 when v_grade='B' then
10 v_info:='very good!!!';
11 when v_grade='C' then
12 v_info:='yiban';
13 else
14 v_info:='No such as grade!!!';
15 end case;
16 dbms_output.put_line(
17 'the grade is ' || v_grade||chr(10)||
18 ' the information is ' || v_info
19 );
20* end;
SQL> /
输入 grade 的值: a
原值 2: v_grade varchar2(1) :=upper('&grade');
新值 2: v_grade varchar2(1) :=upper('a');
the grade is A
the information is excellent!!!!
PL/SQL 过程已成功完成
循环
SQL> ed
已写入 file afiedt.buf
1 declare
2 i int :=1;
3 begin
4 loop 开始
5 dbms_output.put_line(i);
6 i:=i+1;
7 exit when i>10;
8 end loop; 结束
9* end;
SQL> /
1
2
3
4
5
6
7
8
9
10
PL/SQL 过程已成功完成。

数字FOR 循环
SQL> begin
2 for i in 1..10 loop
3 dbms_output.put_line(i);
4 end loop;
5 end;
6 /
1
2
3
4
5
6
7
8
9
10
PL/SQL 过程已成功完成。
双重循环
外循环和内循环都执行5次 ,内外计数器变量名相同 i
显示内循环的计数器和外循环的计数器的乘积
当乘积超过15时候 退出
SQL> ed
已写入 file afiedt.buf
1 begin
2 for i in 1..5 loop
3 for j in 1..5 loop
4 /*
5 exit when i*j>15 ;
6 */
7 if i*j>15 then
8 return;
9 end if;
10 dbms_output.put_line(i*j);
11 end loop;
12 end loop;
13 dbms_output.put_line('test');
14* end;
SQL> /
1
2
3
4
5
2
4
6
8
10
3
6
9
12
15
4
8
12
PL/SQL 过程已成功完成。

SQL> ed
已写入 file afiedt.buf
1 declare
2 i int:=1;
3 begin
4 loop
5 dbms_output.put_line(i);
6 i:=i+1;
7 if i>10 then
8 goto outofloop;
9 end if;
10 end loop;
11 dbms_output.put_line('this is a test text');
12 <<outofloop>>
13 dbms_output.put_line('the last i is ' || i);
14* end;
SQL> /
1
2
3
4
5
6
7
8
9
10
the last i is 11
PL/SQL 过程已成功完成。
写一个PL/SQL 块
想dept表中循环插入5条信息 每一条记录 的deptno值比表中最大的deptno增加1
dname 分别为 "Test1" "Test2" ....."Test5";
SQL> ed
已写入 file afiedt.buf
1 declare
2 mdeptno dept.deptno%type;
3 begin
4 for i in 1..5 loop
5 select max(deptno) into mdeptno from dept;
6 insert into dept values((mdeptno+1),'Test ' || i,null );
7 end loop;
8* end;
9 /
PL/SQL 过程已成功完成。

SQL> rollback;
回退已完成。
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

SQL> ed
已写入 file afiedt.buf
1 declare
2 type num_typ is table of int index by binary_integer;
3 type var_typ is table of varchar2(10) index by binary_integer;
4 /*
5 这是下标的 写法
6 */
7 v_num num_typ;
8 v_var var_typ;
9 v_max dept.deptno%type;
10 /*
11 这是给它赋值
12 */
13 begin
14 select max(deptno) into v_max from dept;
15 select rownum,'test' || rownum
16 bulk collect into v_num,v_var
17 from dual
18 connect by rownum<=5;
19 forall i in v_num.first..v_num.last
20 insert into dept values((v_num(i)+v_max),v_var(i),null);
21 commit;
22* end;
SQL> /
PL/SQL 过程已成功完成。
然后查询
SQL>