oracle 存储过程
存储过程中可以包含逻辑控制语句和数据操纵语句,它可以接受参数、输出参数、返回单个或多个结果集以及返回值。
一个最简单的存储过程必须包含以下关键字:create,procedure,存储过程名称,IA/AS,PL/SQLB标准执行语句
1 create --存储过程头部区域开始 2 or replace --可选表示如果数据库中已存在一条或者相同得名称的存储过程就把它替换掉 3 procedure 4 proc_emp_create --存储过程名称 procedure_name 5 ( 6 empno number,enmae varchar2,job varchar2,mgr varchar2,hiredate date,sal number,common number,deptno number 7 ) --parameter_declaration 声明参数(不需要写长度),存储过程头部区域结束 8 as 9 --声明区域,不需要声明变量可以不写 10 begin --PL/SQL标准执行语句 11 insert into emp values (empno,enmae, job, mgr, hiredate, sal, common, deptno); 12 end;
既然存储过程已经写好并编译完成了,接下来就是使用我们创建的存储过程了。使用存储过程有两种方法:
第一种方法是直接在SQL窗口中,执行SQL语句
1 begin 2 proc_emp_create(7778,'Alexander','analyst',6789,sysdate,4321,'',20); 3 end;
第二种方法是在命令窗口中使用execute命令
1 Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 2 Connected as scott 3 4 SQL> execute proc_emp_create(7778,'Alexander','analyst',6789,sysdate,4321,'',20); 5 6 PL/SQL procedure successfully completed 7 8 SQL>
单条数据查询:
1 create or replace procedure proc_emp_read 2 as 3 v_no number;--声明变量 4 begin 5 select count(empno) into v_no from emp;--在执行代码块里面查询一定要使用into赋值 6 dbms_output.put_line(v_no); 7 end;
参数传入模式: PL/SQL存储过程中有三种传参模式in,out,in out,默认情况下(不写)为in模式
--in,out,in out 模式测试 create or replace procedure proc_param_demo(p1 in number,p2 out number,p3 in out number) as begin dbms_output.put_line('测试in 模式存储过程中p1的值为:' ||p1); --标准输出 dbms_output.put_line('测试out 模式存储过程中p2的值为:' ||p2'); dbms_output.put_line('测试in out 模式存储过程中p3的值为:' ||p3'); --p1 :=100; --报错 p2 := 100; -- := PL/SQL标准赋值 p3 :=100; end;
调试完错误之后,调用上面的存储过程,这次调用我们不直接把值传递给存储过程的参数。所以需要使用declare关键字来声明变量,然后就可以在执行区域才可以使用这些变量
1 declare --声明区域 2 p1 number; 3 p2 number; 4 p3 number; 5 begin 6 p1 := 10; 7 p2 := 10; 8 p3 := 10; 9 proc_param_demo(p1,p2,p3); 10 dbms_output.put_line('测试in 模式存储过程后p1的值为:'||p1); 11 dbms_output.put_line('测试out 模式存储过程后p2的值为:'||p2); 12 dbms_output.put_line('测试in out模式存储过程后p3的值为:'||p3); 13 end;
输出结果如下图所示:
通过测试可以得到以下结果:
- in模式可以理解为引用传递,它的值被完整的传入到存储过程中,但在执行过程中不能被重新赋值,我们传递的值执行之后不会发生改变。
- out模式为值传递,它的值在传入到存储过程的时候会默认赋值为null,可以在执行的时候为其赋值,执行之后传递的值也会随之改变
- in out模式为值传递,它的值被完整的传入到存储过程中,可以在执行的时候为其赋值,执行之后传递的值也会随之改变
总结:可以把in模式看做是向存储过程传递的不想被改变的参数,可以把out模式看做返回值,当执行之后out模式的值就会随着业务逻辑发生改变以供我们使用,而in out模式则很灵活,我们即可以把它当参数传递,也可以当做返回值来使用。
IF 判断语句
1 IF 条件 THEN 2 执行体; 3 END IF;
1 IF 条件 THEN 2 执行体; 3 ELSE 4 执行体; 5 END IF;
1 IF 条件 THEN 2 执行体; 3 ELSEIF 条件 THEN 4 执行体; 5 ELSE 6 执行体; 7 END IF;
CASE选择语句
1 CASE 变量 2 WHEN 匹配变量 THEN 执行体; 3 WHEN 匹配变量 THEN 执行体; 4 WHEN 匹配变量 THEN 执行体; 5 ELSE 执行体; 6 END CASE;
LOOP循环语句
1 LOOP 2 执行体; 3 IF 条件 THEN 4 执行体; 5 EXIT;--此处为跳出循环 6 END IF; 7 END LOOP
1 LOOP 2 执行体; 3 EXIT WHEN 条件;--跳出循环 对比的有CONTINUE和CONTINUE WHEN语法 4 END LOOP
1 FOR i IN 1..3 LOOP -- FOR EACH 语法,遍历1~3并输出 2 --执行体; 3 DBMS_OUTPUT.PUT_LINE (TO_CHAR(i)); 4 END LOOP;
Cursor游标
可以把Cursor理解为一个有名称的结果集,当需要的时候就可以拿过来用,也可以吧Cursor看成一个实体类,存储了我们定义的数据。
1 create or replace procedure proc_cursor_demo as 2 cursor emp_cursor is --定义cursor 3 select * from emp; --将数据空间指向emp_cursor 4 begin 5 for emp_data in emp_cursor loop --遍历cursor数据输出 6 dbms_output.put_line(emp_data.ename ||' 的工作为: '||emp_data.job); 7 end loop; 8 end;
练习题:把emp表中有奖金的员工提取到另外一个表,并在员工的姓名后添加后缀_V
1 create or replace procedure proc_copy_demo 2 (tn in varchar) 3 as 4 v_count number; --检查是否已经有这个名词的表了 5 tablename varchar2(20) --表名称 6 v_emp_copy emp%rowtype --表结构 7 8 v_sql varchar(200) --sql 9 10 cursor emp_data_cursor is --将有emp表中有奖金的人员放到cursor中 11 select * from emp where comm >0; 12 13 begin 14 tablename := tn; 定义表名称 15 select count(*) into v_count from user_objects where object_name = upper(tablename); --查询用户表,校验是否已经存在名称为tablename的表 16 if v_count > 0 then --表存在 17 excute immediate 'drop table' || tablename || 'cascade constraints'; --执行删除表 excute imediate 执行sql语句 18 end if; 19 20 execute immediate 'create table' || tablename || 'as select * from emp where 1=2'; --新建表结构和emp相同的表,添加条件后只创建表,不添加数据 21 for emp_data in emp_data_cursor loop 22 v_emp_copy.empno := emp_data.empno; 23 v_emp_copy.ename := emp_data.ename || '_A'; 24 v_emp_copy.job := emp_data.job; 25 v_emp_copy.mgr := emp_data.mgr; 26 v_emp_copy.hiredate := emp_data.hiredate; 27 v_emp_copy.sal := emp_data.sal; 28 v_emp_copy.comm := emp_data.comm; 29 v_emp_copy.deptno := emp_data.deptno; 30 31 v_sql : = 'insert into' || tbalename ||'values 32 ('||v_emp_copy.empno ||',''' 33 ||v_emp_copy.ename ||''',''' 34 ||v_emp_copy.job ||''',' 35 ||v_emp_copy.mgr ||',''' 36 ||v_emp_copy.hiredate ||''',' 37 ||v_emp_copy.sal ||',' 38 ||v_emp_copy.comm ||',' 39 ||v_emp_copy.deptno ||')'; 40 dbms_output.put_line(v_sql); 41 execute immediate v_sql; 42 end loop; 43 commit; 44 exception -- 捕获异常常用写法 45 when others then 46 dbms_output.put_line('捕获的异常代码(SQLCODE) 为 ' ||SQLCODE ); -- 输出异常信息 47 dbms_output.put_line('捕获的异常信息(SQLERRM) 为 ' ||SQLERRM); 48 end; 49 50 51 -------------------------test------------------------------- 52 begin 53 proc_copy_demo('emp_copy'); 54 end; 55 -------------------------test------------------------------- 56
参考:http://www.cnblogs.com/Singleorb/p/6231364.html