begin
v_deptno emp.deptno%type:=&deptno;
update emp set sal=sal*1.1 where deptno=v_deptno;
if sql%found then dbms_output.put_line('执行成功') ;else dbms_output.put_line('执行失败');
end;
sql%rowcount -- 修改的sql行数
declare
v_deptno emp.deptno%type;
begin
v_deptno:=no;
case v_deptno
when 10 then update emp set comm=100 where deptno=v_deptno;
when 20 then update emp set comm=200 where deptno=v_deptno;
when 30 then update emp set comm=300 where deptno=v_deptno;
else
dbms_output.put_line("不存在");
end case;
end;
-- goto
declare
i int :=1;
begin
loop
insert into temp values(i);
if i=10 then
goto end_loop
end if;
i:=i+1;
end loop;
<<end_loop>>
dbms_output.put_line('循环结束');
end;
-- 复合数据类型
type emp_record_type is record(
name emp.ename%type,
sal emp.sal%type,
dno emp.deptno%type
);
emp_record emp_record_type;
declare
type emp_record_type is record(
name emp.ename%type,
sal emp.sal%type,
dno emp.deptno%type);
emp_record emp_record_type;
begin
select ename,sal,deptno into emp_record from emp where empno=&empno;
dbms_output.put_line(emp_record.name);
end;
-- plsql 单行多列数据
decalre
dept_record dept%rowtype;
begin
dept_record.deptno:=50;
delete from dept where deptno=dept_record.deptno;
update dept set row = dept_record where deptno=&deptno;
end;
-- 索引表 在索引表中使用BINARY_INTEGER和PLS_INTEGER
declare
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
begin
select ename into ename_table(-1) from emp where empno=&no;
end;
-- 在PL/SQL块中使用嵌套表:使用嵌套表变量时,必须首先使用构造方法初始化嵌套表变量,然后才能在块内引用嵌套表元素
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
empno emp.empno%type;
begin
empno := 1;
ename_table := ename_table_type('mary','mary','mary');
for empno in 1..100 loop
select ename into ename_table(emono) from emp where empno=empno;
end loop;
end;
-- VARRAY 变长数组
declare
type ename_table_type is varray(20) of emp.ename%type;
ename_table := ename_table_type('mary');;
begin
select ename into ename_table(1) from emp where empno=&no;
end;
-- 多行多列
declare
type ename_table_type is table of emp%rowtype index by binary_integer;
emp_table ename_table_type;
begin
select * into emp_table from emp where empno=&no;
dbms_output.put_line('雇员名:'||emp_table(1).ename);
dbms_output.put_line('雇员工资:'||emp_table(1).sal);
end;
-- 二维索引表
declare
type a1_table_type is table of number index by binary_integer;
type nal_table_type is table of a1_table_type by binary_integer;
nv1 nal_table_type;
begin
nv1(1)(1):=10;
nv1(1)(2):=5;
nv1(2)(1):=199;
nv1(2)(2):=50;
dbms_output.put_line('显示二维数组的所有元素!');
for i in 1..nv1.count loop
for j in 1..nv1(i).count loop
dbms_output.put_line('nv1('||i||','||j||')='||nv1(i)(j));
end loop;
end loop;
end;
-- 集合赋值 赋null 判断集合是否null
declare
type name_varry_type is varray(4) of varchar2(10);
name_array name_varry_type;
name_empty name_varry_type;
begin
name_array:=name_varry_type('scott','smith');
dbms_output.put_line('name_aray的原有元素的个数:'||name_array。count);
name_array:=name_empty;
if name_array is null then
dbms_output.put_line('name_array的现有的元素个数:0');
end if;
end;
-- set 取消嵌套表的重复
delcare
type nt_table_type is table of number;
nt_table nt_table_type := nt_table_type(2,4,3,1,2);
result nt_table_type;
begin
result:=set(nt_table);
for i in 1..result.count loop
dbms_output.put_line(''||result(i));
end loop;
dbms_output.new_line;
end;
-- multiset union 操作符:取得两个嵌套表的并集.结果集中会包含重复值
-- MULTISET UNION DISTINCT 操作符:用于取得两个嵌套表的并集,并取消重复结果.
-- MULTISET INTERSECT 操作符:用于取得两个嵌套表的交集
-- MULTISET EXCEPT 操作符:取得两个嵌套表的差集.在NT1中存在,但在NT2中不存在
-- 检查集合是否为空 null
decalre
type name_table_type is table of varchar2(10);
name_table name_table_type;
begin
if name_table is empty then
dbms_output.put_line('name_table未初始');
end if;
end;
-- 比较嵌套表是否相同 用“=” 且不能用于索引表和可变数组varray
-- 使用操作符SUBMULTISET OF:用于确定一个嵌套表是否为另一个嵌套表的子集.
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(1,2,3,4);
begin
if nt1 submultiset of nt2 then
dbms_output.put_line('nt1是nt2的子集);
end if;
end;
-- 使用操作符MEMBER OF :用于检测特定数据是否为嵌套表的元素.
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,5);
v1 number:=&v1;
begin
if v1 member of nt1 then
dbms_output.put_line('v1是nt1的元素');
end if;
end;
-- 使用操作符IS A SET:用于检测嵌套表是否包含重复的元素值
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,5);
begin
if nt1 is a set then
dbms_output.put_line('嵌套表NT1无重复值');
end if;
end;
-- FORALL语句 执行批量insert,update,delete操作时,使用forall语句,FORALL不是循环语句
-- insert
declare
type id_table_type is table of number(6) index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
begin
for i in 1..10 loop
id_table(i):=i;
name_table(i):='name'||to_char(i);
end loop;
forall i in 1..name_table.count
insert into demo values(id_table(i),name_table(i));
end;
-- update
declare
type id_table_type is table of number(6) index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
begin
for i in 1..5 loop
id_table(i):=i;
name_table(i):='n'||to_char(i);
end loop;
forall i in 1..id_table.count
update demo set name=name_table(i) where id=id_table(i);
end;
-- delete
declare
type id_table_type is table of number(6) index by binary_integer;
id_table id_table_type;
begin
for i in 1..3 loop
id_table(i):=i;
end loop;
forall i in 1..id_table.count
delete from demo where id=id_table(i);
end;
-- 在FORALL语句上使用INDECES OF子句:用于跳过NULL集合元素
forall i in indices of id_table
-- 在FORALL语句上使用VALUES OF子句
forall i in values of index_pointer
-- 使用SQL%BULK_ROWCOUNT属性:专门为FORALL语句提供,用于取得在执行批量绑定操作时第i个元素所作用的行数
declare
type dno_table_type is table of number(3);
dno_table dno_table_type:=dno_table_type(10,20);
begin
forall i in 1..dno_table.count
update emp set sal=sal*1.1 where deptno=dno_table(i);
dbms_output.put_line('第2个元素更新的行数:'||sql%bulk_rowcount(2));
end;
-- 在select into 语句中使用BULK COLLECT 子句:可以一次将SELECT语句的多行结果检索到集合变量中
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
begin
select ename bulk collect into ename_table from emp;
for i in 1..ename_table.count loop
dbms_output.put_line('ename_table('||i||'):'||ename_table(i));
end loop;
end;
-- 游标 单行数据
declare
cursor emp_cursor is select ename,sal from emp where deptno = 10;
v_ename emp.ename%type;
v_sal emp.ename%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal;
eixt when emp_cursor%notfound;
dbms_output.put_line(v_ename||': '||v_sal);
end loop;
close emp_cursor;
end;
-- 游标 多行数据
declare
cursor emp_cursor is select ename from emp where sal > 10000;
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
begin
open emp_cursor;
loop
fetch emp_cursor bulk collect into ename_table;
exit when emp_cursor%notfound;
end loop;
close emp_cursor;
for i in 1..ename_table.count loop
dbms_output.put_line('工资超过10000员工:'||ename_table(i));
end loop;
end;
-- 游标 多行数据 限制读取行数
declare
cursor emp_cursor is select ename from emp where sal > 10000;
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
rows number:=8;
begin
open emp_cursor;
loop
fetch emp_cursor bulk collect into ename_table limit rows;
exit when emp_cursor%notfound;
end loop;
close emp_cursor;
for i in 1..ename_table.count loop
dbms_output.put_line('工资超过10000员工:'||ename_table(i));
dbms_output.put_line('员工数:'||emp_cursor%rowcount);
end loop;
end;
-- 基于游标定义记录变量
declare
coursor emp_coursor is select ename,sal from emp where empno = 10;
emp_record emp_coursor%rowtype;
begin
open emp_coursor;
loop
fetch emp_coursor into emp_record;
exit when emp_coursor%notfound;
end loop;
close emp_coursor;
end;
-- 参数游标
定义参数游标时,游标参数只能指定数据类型,而不能指定长度.
declare
coursor emp_coursor(no number) is select ename,sal from emp where empno = no;
emp_record emp_coursor%rowtype;
begin
open emp_coursor(10);
loop
fetch emp_coursor into emp_record;
exit when emp_coursor%notfound;
dbms_output.put_line('员工姓名:'||emp_record.ename||'员工工资:'emp_record.sal);
end loop;
close emp_coursor;
end;
-- 使用游标更新或删除数据
要通过游标更新或删除数据,在定义游标时必须要带有FOR UPDATE子句
cursor cursor_name(parameter_name datetype) is select_statement for update [of column_reference] [nowait]
for update子句用于在游标结果集数据上家行共享锁,防止其他用户在相应行执行DML操作
of子句确定哪些表要加锁,没有OF子句,则在所引用的全部表上加锁
nowait子句用于指定不等待锁
必须在UPDATE后DELETE语句中引用WHERE CURRENT OF子句
update table_name set column=.. where current of cursor_name;
delete table_name where current of cursor_name;
declare
cursor emp_cursor is select ename,sal from emp for update;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal;
exit when emp_cursor%notfound;
if v_oldsal < 2000 then
update emp set sal=sal+1000 where current of emp_cursor;
end if;
end loop;
close emp_cursor;
end;
-- 使用游标for循环
每循环一次提取一次数据,在提取了所有数据后,自动退出循环并隐含的关闭游标
delare
cursor emp_cursor is select ename,sal from emp;
begin
for emp_record in emp_cursor loop
dbms_output.put_line('第'||emp_cursor%rowcount||'个雇员'||emp_record.ename);
end loop;
end;
-- 在游标FOR循环中直接使用子查询
begin
for emp_record in (select ename,sal from emp)loop
dbms_output.put_line(emp_record.ename);
end loop;
end;
-- 游标变量使用示例
-- 在定义FEF CURSOR类型时不指定RETURN子句
declare
type emp_cursor_type is ref cursor;
emp_cursor emp_cursor_type;
emp_record emp%rowtype;
begin
open emp_cursor for select * from emp where deptno=10;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('第'||emp_curosr%rowcount||'个雇员: '||emp_record.ename);
end loop;
close emp_cursor;
end;
-- 在定义FEF CURSOR类型时指定RETURN子句
declare
type emp_record_type is record(name varchar2(10),salary number(6,2));
type emp_cursor_type is ref cursor return emp_record_type;
emp_cursor emp_cursor_type;
emp_record emp_record_type;
begin
open emp_cursor for select ename,sal from emp where deptno = 20;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('第'||emp_curosr%rowcount||'个雇员: '||emp_record.ename);
end loop;
close emp_cursor;
end;
-- 使用纯度级别
-- 为了对包的公用函数加以限制,在定义包规范时,可以使用纯度级别(purity level)限制公用函数
语法:pragma restrict_references (function_name,wnds[,wnps][,rnds][,rnps]);
wnds:用于限制函数不能修改数据库数据(禁止DML)
wnps:用于限制函数不能修改包变量(不能给包变量赋值)
rnds:用于限制函数不能读取数据库数据(禁止SELECT操作)
rnps:用于限制函数不能读取包变量(不能将包变量赋值给其他变量)
1.建立包规范
create or replace package purity is
minsal number(6,2);
maxsal number(6,2);
function max_sal return number;
function min_sal return number;
pragma restrict_references(max_sal,wnps);--不能修改
pragma restrict_references(min_sal,wnps);
end;
2.建立包体
create or replace package body purity is
function max_sal return number
is
begin
return maxsal;
end;
function min_sal return number
is
begin
return minsal;
end;
begin
select min(sal),max(sal) into minsal,maxsal from emp;
end;
end purity;
-- 语句触发器
create or replace trigger tr_sec_emp
before insert or update or delete on emp
begin
if to_char(sysdate,'DY','nls_date_language=AMERICAN') in ('SAT','SUN')
then
raise_application_error(-20001,'不能在休息日改变雇员信息');
end if;
end
-- 行触发
-- 建立BEFORE行触发器
create or relpace trigger tr_emp_sal
before update of sal on emp
for each row
begin
if :new.sal<:old.sal then
raise_application_error(-20010,'工资只涨不降');
end if ;
end;
-- 批量动态SQL
create or replace procedure drop_table(table_name varchar2)
is
sql_statement varchar2(100);
begin
sql_statement := 'drop table'||table_name;
execute immediate sql_statement;
end;
exec drop_table('worker');
-- 当直接使用EXECUTE IMMEDIATE处理带有RETURNING子句的DML时,只能处理作用在单行上的DML语句
如果DML语句作用在多行上,则必须要使用BULK子句
declare
salary number(6,2);
sql_stat varchar2(100);
begin
sql_stat := 'update emp set sal=sal*(1+perccent/100)'||' where empno=:eno returning sal into :salary';
execute immediate sal_stat using &1,&2 returning into salary;
dbms_output.put_line('新工资:'||salary);
end;
-- 多行查询实例
declare
type emp_cursor_type is ref cursor;
type ename_table_type is table of emp.ename%type index by binary_integer;
type sal_table_type is table of emp.salary%type index by binary_integer;
ename_table ename_table_type;
sal_table sal_table_type;
emp_cursor emp_cursor_type;
emp_record emp%rowtype;
sql_stat varchar2(100);
begin
sql_stat:='select * from emp where deptno=:dno'||'returning ename,sal into :name,:salary';
open emp_cursor for sql_stat using &dno return ename_table,sal_table;
loop
fetch emp_cursor bulk collect into emp_record;
eixt when emp_cursor%notfound;
dbms_output.put_line('雇员名:'||emp_record.ename||',工资:'||emp_record.sal);
end loop;
close emp_cursor;
end;
-- 对象实体 static、member
-- static方法用于访问对象类型,在对象类型上执行全局操作
-- STATIC方法只能由对象类型访问,不能由对象实例访问
-- MEMBER方法用于访问对象实例的数据,如果在对象类型中需要访问特定对象实例的数据,则必须要定义MEMBER方法.
-- MEMBER方法只能由对象实例调用,而不能由对象类型调用.
-- 建立对象类型
create or repalce type person_type3 as object(
name varchar2(10),gender varchar2(2),
birthday date,regdate date,
static function get_date return date,
member function get_info return varchar2);
-- 建立对象类型实体
create or replace type body person_type3 is
static function get_date return date is
begin
return sysdate;
end;
member function get_info return varchar2
is
begin
return '姓名:'||name||',注册日期:'||regdate;
end;
end;
-- 在对象类型上使用STATIC方法:对象类型调用
begin
insert into employee_tab3(eno,sal,job,person) values(&no,&salary,'&title',person_typ3("&name','&sex','&birthdate',person_typ3.getdate()));
-- 使用MEMBER方法:实例对象调用
declare
v_person person_typ3;
begin
select person into v_person from employee_tab3 where eno=&no;
dbms_output.put_line(v_person.get_info());
end;
-- 使用对象类型继承时,在定义父类型时必须要指定NOT FINAL 选项,如果不指定该选项,默认为FINAL,表示该对象类型不能被继承
-- 建立父对象:
create or replace type person_type9 as object(
name varchar2(10),gender varchar2(2),birthdate date,address varchar2(50),
member function get_info return varchar2)not final;
-- 建立对象类型体
create or replace type body person_type9 as
member function get_info return varchar2
is
begin
return '姓名:'||name||',家庭住址:'||address;
end;
end;
-- 建立子对象类型(继承)
create or replace type employee_type9 under person_type9(
eno number(6),sal number(6,2),job varchar2(10),
member function get_other return varchar2);
-- 建立对象的类型的(私有方法)
create or repalce type body employee_type9 as
member function get_other return varchar2
is
begin
return '雇员名称:'||name||',工资:'||sal;
end;
end;
-- 调用建立对象表
sql> create table employee_tab9 of employee_tab9;
sql> insert into employee_tab9 values('马丽','女','01-11月-76','呼和浩特15号',2,2000,'高级钳工');
declare
v_employee employee_type9;
begin
select value(a) into v_employee from employee_tab9 a where a.eno=&no;
dbms_output.put_line(v_employee.get_info);
dbms_output.put_line(v_employee.get_other);
end;
-- 在定义部分定义例外名,然后在例外和ORACLE错误之间建立关联,最终在例外处理部分捕捉并处理例外.
当定义ORACLE错误和例外之间的关联关系时,需要使用伪过程EXCEPTION_INIT
declare
e_integrity exception;
pragma exception_init(e_integrity,-2291);
begin
update emp set deptno=&dno where empno=&eno;
exception
when e_integrity then
dbms_output.put_line('该部门不存在');
end;