(1)声明部分(DECLARE)开始(可选),到BEGIN关键字结束,这一部分可以声明PL/SQL程序块中所用到的变量、常量和游标等。
注:再某个PL/SQL块中声明的内容,只能在当前块中使用
(2)执行部分(BEGIN)开始(必须有),结束方式有两种。如果语句块中运行出现异常,则执行异常处理部分的代码结束。如果代码块没有异常,则以执行到END关键字结束。
(3)异常处理部分(EXCEPTION),语句块出现异常时执行该部分,执行结束后,整个PL/SQL语句块执行结束。
注:每一条语句都必须以分号结束,每条SQL语句可以写成多行,以分号结束;
单行注释 –
多行注释 /。。。。。/
p标识精度(所有有效数字) s标识刻度范围(小数点右边的位数)
Char长度固定,最大2000字节
Varchar2长度不固定,最大4000字节
Long长度不固定,最大32767字节
优点
(1)用户不必查看表结构中各列的数据类型就可以定义保存某列值的变量
(2)如果对表中列的类型进行修改,无需考虑更改pl/sql语句块中定义的变量类型
Select…into 对变量进行赋值
存储由多列组成的一行数据,是一种结构化的数据类型,使用type语句进行定义
结合了%TYPE和RECORD变量的优点,可以根据数据表中行的结构,定义一种特殊的数据类型,用来存储从数据表中检索到的一行数据
declare
--定义能够存储emp表中一行数据的变量
row_emp emp%rowtype;
begin
--检索数据存储到定义的变量
select *
into row_emp
from emp
where empno = 7369;
--输出查询的数据
dbms_output.put_line('雇员'||row_emp.ename||'的编号'||
row_emp.empno||'职务是'||row_emp.job);
end;
只做一种情况条件判断
declare
var_name1 varchar2(50);
var_name2 varchar2(50);
begin
var_name1 := 'AAA';
var_name2 := 'BB';
if length(var_name1) > length(var_name2) then
dbms_output.put_line('字符串'||var_name1||'的长度比字符串'
||var_name2||'的长度大');
end if;
end;
可以实现判断两种情况分支
declare
age int := 20;
begin
if age >= 18 then
dbms_output.put_line('你已经老了');
else
dbms_output.put_line('你还年轻');
end if;
end;
实现多分支选择语句
declare
--定义月份变量
month int;
begin
--获取系统当前时间月份,赋值给month变量
select to_char(sysdate,'MM')
into month
from dual;
--判断是第几季度
if month >= 1 and month <=3 then
dbms_output.put_line('这是第一季度');
elsif month >=4 and month <=6 then
dbms_output.put_line('这是第二季度');
elsif month >=7 and month <=9 then
dbms_output.put_line('这是第三季度');
elsif month >=10 and month <=12 then
dbms_output.put_line('这是第一季度');
else
dbms_output.put_line('月份不符合要求');
end if;
end;
与elseif类似,case后面通常是一个变量
declare
season int :=3;
info varchar2(50);
begin
case season
when 1 then
info := '季度包含1,2,3月份';
when 2 then
info := '季度包含4,5,6月份';
when 3 then
info := '季度包含7,8,9月份';
when 4 then
info := '季度包含10,11,12月份';
else info := '季度不合法';
end case;
dbms_output.put_line(info);
end;
Loop语句会先执行一次循环体,然后判断‘EXIT WHEN’关键字后面的条件表达式,若为true则退出循环体,否则继续执行循环体,所以loop至少执行一次循环体
declare
--定义整数变量,存储整数和
sum_i int := 0;
--定义整数变量,存储自然数
i int := 0;
begin
--循环累加
loop
--给自然数赋值
i := i+1;
--计算前n个自然数的和
sum_i := sum_i+i;
--当循环100次时,程序退出循环体
exit when i = 100;
end loop;
dbms_output.put_line('前100个自然数之和为:'||sum_i);
end;
执行0次或多次循环体,在每次执行循环体之前,首先判断条件表达式的值是否为true,若为true在执行循环体语句,否则退出循环体
declare
sum_i int := 0;
i int :=0;
begin
while i <= 100 loop
i := i+1;
sum_i := sum_i + i;
end loop;
dbms_output.put_line(sum_i);
end;
For语句是一个可以预置循环次数的循环控制语句,它有一个循环计数器,通常是一个整型变量,通过这个循环计数器来控制循环次数
declare
sum_i int := 0;
begin
for i in reverse 1..100 loop
--判断是否为偶数
if mod(i,2) = 0 then
sum_i := sum_i + i;
end if;
end loop;
dbms_output.put_line('和为'||sum_i);
end;
声明游标
主要包括游标名和为游标提供结果集的select语句,因此声明游标时必须指定游标名和游标所使用的select语句
打开游标
游标声明完之后,必须打开才能使用
Open 游标名称[()],当省略参数后,传入的就为默认值
读取游标
读取游标就是逐行将结果集中的数据保存到变量中处理。
Fetch cur_name into(variable)
Variable:一个变量列表或‘记录’变量(record类型)
%found:布尔值,存在值为true,否则为false
关闭游标
Close cur_name;
实例:
declare
--声明游标
cursor cur_emp(var_job in varchar2 := 'SALESMAN')
is select empno,ename,sal
from emp
where job = var_job;
--声明一个记录类型,用于存放游标每行的值
type reco_emp is record
(
var_empno emp.empno%type,
var_ename emp.ename%type,
var_sal emp.sal%type
);
--声明一个reco_emp类型的变量
emp_row reco_emp;
begin
--打开游标
open cur_emp('MANAGER');
--先让指针指向结果集中的第一行
fetch cur_emp into emp_row;
while cur_emp%found loop
dbms_output.put_line(emp_row.var_ename||'编号是'||
emp_row.var_empno||'工资为'||emp_row.var_sal);
fetch cur_emp into emp_row;
end loop;
--关闭游标
close cur_emp;
end;
将emp表中销售员的工资上调20%,然后使用隐式游标sql的%rowcount属性输出上调员工的数量
%rowcount受sql语句影响的行数
begin
update emp
set sal = sal*1.2
where job = 'SALESMAN';
if sql%notfound then
dbms_output.put_line('没有雇员需要上调工资');
else
dbms_output.put_line('有'||sql%rowcount||'个雇员工资上调20%');
end if;
end;
自定义异常:业务逻辑异常
drop trigger tri_ddl_oper;
连接视图指基于多个表所建立的视图。使用连接视图主要目的是为了简化连接查询。需要注意,连表查询时,必须使用where子句指定有效的连接条件,否则结果就是毫无意义的笛卡尔积
drop view emp_view_uni;