PL/SQL(1)

PL/SQL(一)1 过程,函数,触发器 用PL/sql编写,这些都是在Oracle中PL/sql是很强大的过程化语言,可以被Java调

PL/SQL(一)
1 过程,函数,触发器 用PL/sql编写,这些都是在Oracle中PL/sql是很强大的过程化语言,可以被Java调用
提升应用程序的性能:如果用传统的操作数据库java 程序发送sql,数据库编译,编译的过程要消耗时间,而过程,函数不必经过编译这一过程
1 优化sql 2 还不行就用过程,函数缺点:移植性不好

存储过程:添加普通过程create procedure myprocedure is?begin??insert into emp values(23,'myname'......);end;/ -- ?后面机上/让Oracle去创建如果有了存储过程的话,要替换这个myprocedurecreate or replace procedure myprocedure is begin ...end;查看错误信息 show errow;调用过程第一种exec ?过程名[(参数1,参数2....)];第二种 call ?过程名[(参数1,参数2....)];exec myprocedure;
块: 过程,函数,触发器,包
编写规范注释单行注释 --多行 ? ? /*.......*/符号命名变量 v_xxx常量 c_xxx游标 xxx_cursor例外 e_xxx (e_error)块:三部分:定义部分,执行部分,例外部分declear ?定义部分 ?可选begin执行部分dbms_output.put_line('test');exception 例外部分 可选end;
dbms_output 是Oracle提供的包,

set serveroutput off; -- off/on 打开关闭输入


declare?v_ename varchar2(20)bigin?select ename into v_ename from empwhere empno = &aaa;dbms_output_put_line('员工名:'||v_ename);end?执行后会弹出一个输入aaa的框,然后输出。

declare?v_ename varchar2(20);v_sal number(7,2);bigin?select ename,sal into v_ename,v_sal from empwhere empno = &aaa;dbms_output_put_line('员工名:'||v_ename||'薪水'||val);exceptionwhen no_data_found thendbms_output_put_line('输入有误');end?


传递参数 myprocedure(name varchar2,sal number) 参数只需要声明什么类型就行了
create procedure myprocedure(newname varchar2,newsal number) isbeginupdate emp set sal = newsal where ename = newname; ?end;

exec ?myprocedure('SCOTT',8888)
java 调用过程
CallableStatement ?cs = conn.propareCall("{call muprocedure(?,?)}");cs.setString(1,"SMITH");cs.setInt(2,100000);cs.execute();

函数函数是用于返回特定的数据,只返回一个值,在函数头部必须包含return子句, 函数体内必须包含return语句返回的数据通过名字得到员工年薪create function myfun(name varchar2)return number isyearnumber number(7.2);begin?select (sal+comm)*12 into yearsal from emp where ename= name;?return yearsal;end;--调用var income numbercall myfun('SCOTT') into:income;print income---------------
java调用函数select mypro('SCOTT') from dual然后rs.getInt(1);?
包包是用于逻辑上组合过程和函数的,由包规范和包体组成create package mypackage is?? ?procudure mypro(name varchar2,sal number);?? ?function myfun(name varchar2) return number;end;
然后创建包体,给把mypackage 实现包体create [or replace] package body mypackage isprocedure mypro(newname varchar2,newsal number) is?begin?update emp set sal = newsal where ename = newname; ?end;
create function myfun(name varchar2)return number isyearnumber number(7.2);begin?select (sal+comm)*12 into yearsal from emp where ename= name;?return yearsal;end;end;
调用包的过程或者函数exec mypackage.mypro('SCOTT',8989);


触发器隐含执行的存储过程,必须指定触发事件和触发的操作。常用触发事件insert,update,delete。

变量类型1 标量类型 ?scalar2 复合类型 ?composite3 参照类型 ?reference4 lob ? ?large object标量scalar是一种常用的类型

定义常量和变量的语法 identifier [constant] datatype [not null] [:=| default expr]
identifier:名称constant ?:指定常量,需要指定它的初始值,且其值是不能改变的datatype :数据类型not null:指定变量不能为null:= ?给变量或者是常量指定初始值default 用于指定初始值expr:指定初始值的PL/sql 表达式,可以为文本值,其他变量,函数等。

标量定义(存放单个变量)1 定义变长字符串 ?v_ename varchar2(20)2 定义一个小数 ? ?v_sal number(6,2);3 定义一个小数并初始化 ?v_sal number(6,2):=80004 定义date ? v_birth ?date;5 定义布尔变量 ? ? ? v_valid ? boolean not null default false;
输入员工号 显示员工姓名 工资 个人所得税(税率0.03)
declare?c_tax_rate number(3,2):=0.03v_ename varchar2(20);v_sal number(7,2);v_tax_sal number(7,2);beginselect ename,sal into v_ename,v_sal from emp where empno = &no;-- 计算所得税v_tax_sal:= v_sal * c_tax_rate;-- ?输入 省略end??如果要查的员工名字长度大于20 就会报错,如何办? ?%type ?此时可以该该 v_ename emp.ename%type; 这种类型和表的字段类型一致这样就不会出溢出问题
declare?c_tax_rate number(3,2):=0.03v_ename emp.ename%type;v_sal emp.sal%type;v_tax_sal number(7,2);beginselect ename,sal into v_ename,v_sal from emp where empno = &no;-- 计算所得税v_tax_sal:= v_sal * c_tax_rate;-- ?输入 省略end
复合变量 ?composite(用于存放多个值)分为pl/sql记录 ,pl/sql表,(嵌套表,varray(动态表))记录类似于高级语言的结构体(如类似于类)declare type -- 定义一个名为my_c_t (存放多个数据)my_c_t ?is record(name emp.ename%type,salary emp.sal%type,...)mytest my_c_t ?beginselect ename,sal,... into my_c_t from emp where empno = 888;-- dbms_output_put_line('name:'||mytest.ename);end;
pl/sql表相当于高级语言的数组,下表可以为负数,如所有的enamedeclare ?typemy_t_t is talbe of emp.ename%type index by binary_integertest my_t_tbeginselect ename into test(-1) from emp where empno = 888;-- dbms_output_put_line('name:'||test(-1));-- 放在哪个位置就再哪个位置取出end;但是如果select如果返回多行呢? 报错了! 如何办? 用参照变量
参照变量 游标变量(ref cursor用的最多)和对象类型变量(ref obj cursor)
定义游标变量的时候不指定select,打开的时候需要指定输入部门号,显示该部门的员工名和工资1declare typemy_s_t is ref cursor ;beign end;2declare typemy_s_t is ref cursor ;test my_s_t;beign end;3declare typemy_s_t is ref cursor ;test my_s_t;beign?open test for select ename,sal from emp where deptno = &no;end;4 这个时候需要定义两个变量declare typemy_s_t is ref cursor ;v_ename emp.ename%type;v_sal emp.sal%type;test my_s_t;beign?open test for select ename,sal from emp where deptno = &no;loopfetch test into v_enam,v_sal; dbms_output_put_line('name:'v_name||'sal:'||v_sal);end loop;end;5 指定何时退出declare typemy_s_t is ref cursor ;v_ename emp.ename%type;v_sal emp.sal%type;test my_s_t;beign?open test for select ename,sal from emp where deptno = &no;exit when test%notfound;loopfetch test into v_enam,v_sal; dbms_output_put_line('name:'||v_name||'sal:'||v_sal);end loop;end;