--打开日志输出 set serverout on -- PL/SQL 语句块: -- 声明部分 declare v_i number; v_sum number:=0; -- 执行部分 begin v_i := 1; -- 简单loop循环 loop v_sum:=v_sum+v_i; v_i:=v_i+1; if v_i>100 then exit;-- 跳出循环 end if; end loop; dbms_output.put_line(v_sum); -- 异常处理部分 end; -- 循环1 :简单LOOP循环 loop -- 循环体 end loop; -- 退出循环: if 退出条件 then exit; end if; -- 简写的退出条件 exit when 退出条件; -- declare v_s number:=1; v_i number:=1; begin loop v_s:=v_s*v_i; v_i:=v_i+1; exit when v_i>3; end loop; dbms_output.put_line(v_s); end; -- 注意:在sqlplus中要输出,需要打开输出标记: -- SQL> set serveroutput on; -- if语句 if 条件1 then --条件1为true执行语句 elsif 条件2 then --条件2为true执行语句 else --条件1、条件2都为false时执行语句 end if; -- 循环2:while循环 declare v_i number:=1; v_sum number:=0; begin while v_i<=100 loop v_sum:=v_sum+v_i; v_i:=v_i+1; end loop; dbms_output.put_line(v_sum); end; -- 循环3:数值循环for declare v_sum number:=0; begin for v_i in 1..100 loop v_sum:=v_sum+v_i; end loop; dbms_output.put_line(v_sum); end; -- in reverse 反向for循环 begin for v_i in REVERSE 1..10 loop dbms_output.put_line(v_i); end loop; end; -- 查询 declare v_eno number:=7780; v_ename varchar2(20); begin select ename into v_ename from emp where empno=v_eno; dbms_output.put_line(v_ename); exception when no_data_found then dbms_output.put_line(‘没找到数据异常:‘||sqlerrm); when others then-- others 相当于异常父类,可以捕获所有异常 dbms_output.put_line(‘异常:‘||sqlerrm); end; -- 异常消息格式: -- 异常类型(ORA运行异常 PLS编译异常) 异常编号(一个负数:-1 ~ -19999) 异常消息 -- 例如:ORA-01403: 未找到任何数据 -- 自定义异常: -- my_exception_name EXCEPTION; -- 定义异常名称 -- PRAGMA EXCEPTION_INIT(my_exception_name,-2290); -- 为异常编号困绑这个名称 declare my_exception_name EXCEPTION; -- 定义异常名称 PRAGMA EXCEPTION_INIT(my_exception_name,-2291); -- 为异常编号困绑这个名称 begin insert into emp(empno,deptno) values(1000,50); exception when my_exception_name then dbms_output.put_line(sqlerrm); end; -- 手动抛出异常:raise_application_error(异常编号,‘异常消息‘); declare -- 嵌套语句块的外部声明部分 begin -- 嵌套前 declare -- 变量的声明周期:在其定义的begin end 中 v_sex varchar2(20); begin v_sex := ‘&输入性别‘; if not (v_sex = ‘男‘ or v_sex=‘女‘) then -- 抛出异常 raise_application_error(-20000,‘性别只能是男或者女‘); end if; -- 正常输出语句 dbms_output.put_line(‘性别:‘||v_sex); exception when others then dbms_output.put_line(sqlerrm); end; -- 嵌套后 end; -- 列引用类型:%type declare v_ename emp.ename%type; v_sal emp.sal%type; c_constant constant number:=20;-- 定义一个常量 begin select ename,sal into v_ename,v_sal from emp where empno=&员工编号; dbms_output.put_line(v_ename||‘ ‘||v_sal); exception when others then dbms_output.put_line(sqlerrm); end; -- 行引用类型: %rowtype; declare v_row emp%rowtype; begin select * into v_row from emp where empno=&eno; dbms_output.put_line(v_row.ename||‘ ‘||v_row.empno||‘ ‘||v_row.sal||‘ ‘||v_row.deptno); exception when others then dbms_output.put_line(sqlerrm); end; --------- 游标 ---------- declare v_row emp%rowtype; -- 1-定义游标 cursor cur_emp is select * from emp where deptno=10; begin -- 2- 打开游标 open cur_emp; loop -- 3- 提取数据 fetch cur_emp into v_row; -- 提取不到数据时结束循环 exit when cur_emp%notfound; dbms_output.put_line(v_row.empno||‘ ‘||v_row.ename||‘ ‘||v_row.deptno||‘ ‘||v_row.sal); end loop; -- 4- 关闭游标 close cur_emp; exception when others then dbms_output.put_line(sqlerrm); end; /** 游标属性 %found boolean 测试是否提取到数据 %notfound boolean 测试是否未提取到数据 %isopen boolean 测试是否打开 %rowcount number 测试当前操作的行数 */ -- while使用游标 declare cursor cur_emp is select * from emp where deptno=&dno; v_row emp%rowtype; begin if not cur_emp%isopen then open cur_emp; end if; fetch cur_emp into v_row; while cur_emp%found loop dbms_output.put_line(cur_emp%rowcount||‘ ‘||v_row.empno||‘ ‘||v_row.ename||‘ ‘||v_row.deptno||‘ ‘||v_row.sal); fetch cur_emp into v_row; end loop; if cur_emp%isopen then close cur_emp; end if; exception when others then dbms_output.put_line(sqlerrm); end; -- 游标for循环: -- 特点:帮我们做 open fetch close declare cursor cur_emp_dept is select e.empno,e.ename,e.deptno,d.dname,d.loc from emp e join dept d on(e.deptno=d.deptno); -- 使用游标定义行引用类型 v_row cur_emp_dept%rowtype; begin for v_row in cur_emp_dept loop dbms_output.put_line(v_row.empno||‘ ‘||v_row.ename||‘ ‘||v_row.deptno||‘ ‘||v_row.dname||‘ ‘||v_row.loc); end loop; exception when others then dbms_output.put_line(sqlerrm); end; -- 使用游标for循环甚至可以不用定义游标 begin for v_row in (select ename,sal from emp where deptno=20) loop dbms_output.put_line(v_row.ename||‘ ‘||v_row.sal); end loop; end; -- 参数化游标 declare -- 注意:形参禁止带精度,否则编译错误 cursor cur_emp(dno number) is select * from emp where deptno=dno; v_row cur_emp%rowtype; begin -- 打开游标时指定参数 open cur_emp(30); fetch cur_emp into v_row; while cur_emp%found loop dbms_output.put_line(v_row.ename||‘ ‘||v_row.sal||‘ ‘||v_row.deptno); fetch cur_emp into v_row; end loop; close cur_emp; exception when others then dbms_output.put_line(sqlerrm); end; declare -- 注意:形参禁止带精度,否则编译错误 cursor cur_emp(dno number) is select * from emp where deptno=dno; begin for v_row in cur_emp(20) loop dbms_output.put_line(v_row.ename||‘ ‘||v_row.sal||‘ ‘||v_row.deptno); end loop; exception when others then dbms_output.put_line(sqlerrm); end; -- 游标的意义:逐行判断复杂的条件,并更新 -- 更新10部门工资低于3000的人,工资上涨10%; declare cursor cur_emp is select * from emp for update -- 锁定游标指定的结果集 nowait; -- 指定非等待方式 begin for v_row in cur_emp loop if(v_row.sal<3000 and v_row.deptno=10) then -- 条件: 游标指向的当前行 update emp set sal=sal*1.1 where current of cur_emp; end if; end loop; exception when others then dbms_output.put_line(sqlerrm); end; -- 涉及多表操作的更新游标 declare cursor cur_emp is select e.*,d.dname,d.loc from emp e,dept d where d.deptno=e.deptno for update -- 锁定游标指定的结果集 of e.deptno -- 指定锁定emp表(结果集合使用emp的rowid) nowait; -- 指定非等待方式 begin for v_row in cur_emp loop if(v_row.sal<3000 and v_row.deptno=10) then -- 条件: 游标指向的当前行 update emp set sal=sal*1.1 where current of cur_emp; end if; end loop; exception when others then dbms_output.put_line(sqlerrm); end; -- 游标变量 declare -- 定义游标类型 type my_cursor_type is ref cursor; -- 使用游标类型定义游标变量 my_cursor my_cursor_type; v_row emp%rowtype; -- 错误:不能使用普通的游标变量定义行引用类型 --v_row my_cursor%rowtype; begin -- 打开游标时赋予结果集 open my_cursor for select * from emp; loop fetch my_cursor into v_row; exit when my_cursor%notfound; dbms_output.put_line(v_row.empno||‘ ‘||v_row.ename||‘ ‘||v_row.deptno||‘ ‘||v_row.sal); end loop; close my_cursor; exception when others then dbms_output.put_line(sqlerrm); end; -- 定义一个带返回类型的游标类型,生成游标变量 declare -- 定义带返回类型的游标类型 type my_cursor_type is ref cursor return emp%rowtype; -- 使用游标类型定义游标变量 my_cursor my_cursor_type; --v_row emp%rowtype; -- 正确:可以使用带返回类型的游标变量定义行引用类型 v_row my_cursor%rowtype; begin -- 打开游标时赋予结果集 open my_cursor for select * from emp; loop fetch my_cursor into v_row; exit when my_cursor%notfound; dbms_output.put_line(v_row.empno||‘ ‘||v_row.ename||‘ ‘||v_row.deptno||‘ ‘||v_row.sal); end loop; close my_cursor; exception when others then dbms_output.put_line(sqlerrm); end; type cur is ref cursor; 整体的意思是“创建一个类型变量cur,它引用游标”,除了cur外,其余全是关键字。 TYPE cur:定义类型变量 is ref cursor:相当于数据类型,不过是引用游标的数据类型。 这种变量通常用于存储过程和函数返回结果集时使用,因为PL/SQL不允许存储过程或函数直接返回结果集,但可以返回类型变量,于是引用游标的类型变量作为输出参数或返回值就应运而生了
时间: 2024-10-28 14:18:28