1, create or replace procedure sp_pro is
begin
insert into mytest values('123','wangwu');
end;;
查看错误: show error;
执行: /
2,调用;
exec 过程名(参数,参数);
call 过程名(参数,参数,....);
3,块(编程)-->过程,函数,包,触发器
命名规范: 变量v_前缀v_sal , 常量c_前缀c_rate; 游标_cursor后缀emp_cursor; 异常e_前缀e_error;
declear 定义常量、变量、游标、例外异常、复杂数据类型,
begin执行sql语句, exception 异常处理, end;
set serveroutput on --打开输出选项;
declare --定义变量
v_ename varchar2(5);
v_sal number(7,2);
begin
select ename,sal into v_ename, v_sal from emp where empno=&no; --将查询出来的ename放入到参数v_ename中,&表示从控制台接受输入的变量; 参数顺序要一致
dbms_output.put_line('雇员名:'||v_ename); --控制台输出
dbms_output.put_line('hello');
exception --异常处理
when no_data_found then
dbms_output.put_line('数据输入错误');
end;
4,异常例外: no_data_found 数据不存在
create procedure sp_pro3(spName varchar2, newSal number) is ---参数只指定类型不指定大小
begin
update emp set sal=newSal where ename=spName; --根据用户名修改工资
end;
exec sp_pro3('scott', 4678); --调用过程
java调用:
CallableStatement cs=conn.prepareCall("{call sp_pro3(?,?)}");
cs.setString(1,"Tom");//给? 赋值
cs.setInt(2,1000);
cs.execute(); //执行
java调用有返回值的存储过程:
CallableStatement cs=conn.prepareCall("{call sp_pro8(?,?)}");//第一个参数是入参数,第二个是出参数
cs.setString(1,"Tom");//给第一个? 赋值
//给第二个?赋值
cs.registerOutParameter(2,oracle.jdbc.oracleTypes.VARCHAR); //过程的第二个参数为输出参数,类型要一致
cs.execute(); //执行
//取出返回值,要注意?顺序
String name=cs.getString(2); //得到过程的返回值
5 创建函数:
crete function sp_fun2(spName varchar2) --参数不定义大小
return number is yearSal number(7,2);
begin
select sal*12+nvl(comm,0)*12 into yearSal from emp where ename=spName;
return yearSal;
end;
函数调用:
var abc number;
call sp_fun2('scott') into :abc;
print abc
java程序中调用函数:
select sp_fun('scott') from dual;//通过rs.get(1)得到返回的结果。
6 包: 用于逻辑上组合过程和函数,它有包规范和包体两部分组成;
create package sp_package is
procedure update_sal(name varchar2, newsal number);
function annual_income(name varchar2) return number;
end;
包规范只包含了过程和函数的说明,但是没有过程和函数的实现代码。包体用于实现包规范中的过程和函数。
建立包体: create package body sp_package is
procedure update_sal(name varchar2, newsal number)
is
begin
update emp set sal=newsal where ename=name;
end;
function annual_income(name varchar2)
return unmber is
annual_salary number;
begin
select sal*12+nvl(comm,0) into annual_salary from emp where ename=name;
return annual_salary;
end;
end;
调用执行: call sp_package.update_sal('tom',120);
7 定义变量:
1),定义一个变长字符串 v_ename varchar2(10);
2), 定义一个小数范围 -9999.99 ~ 9999.99
v_sal number(6.2);
3),定义一个小数并初始值为5.4 ,:=是赋值号
v_sal2 number:=5.4;
4) 定义一个日期类型的数据
v_brithdate date;
5) 定义一个布尔变量,不能为空,初始值为false
v_valid boolean not null default false;
8,复合变量:记录类型,表类型
declare
type emp_record is record( name emp.ename%type, sal emp.sal%type); --定义一个记录类型
sp_record emp_record; --定义一个记录变量
begin
select ename,sal into sp_record from emp where empno=7788; --赋值
dbms_output.put_line('员工名: '|| sp_record.name); --获取
end;
------------表类型相当于数组------------------------
declare
type sp_table_type is table of emp.ename%type index by binary_integer; --下标为整数可以为负数
sp_table sp_table_type; --定义一个表类型的变量
begin
select ename intosp_table(0) from emp where empno=7788; --赋值,下标为0,只能接受一行的记录
dbms_output.put_line('员工名: '||sp_table(0)); --获取
end;
9,参照表里:游标cursor
declare
type sp_emp_cursor is ref cursor; --定义一个游标类型
sp_cursor sp_emp_cursor; --定义一个游标变量
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open sp_currsor for select ename,sal from emp where deptno=10; --游标与一个select结合
loop
fetch sp_currsor into v_ename,v_sal;--从游标获取数据赋值给变量
exit when sp_curror%notfound; --判断是否为空
dbms_output.put_line('名字: '||v_ename||'工资: '||v_sal);
end loop;
end;
带参数的游标:
declare
cursor c_emp(p_deptno employees.department_id%type)is
select * from hr.employees where department_id=p_deptno;
v_emp c_emp%ROWTYPE;
begin
open c_emp(10);
loop
fetch c_emp into v_emp;
exit when c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp.employ_id||v_emp.last_name);
end loop;
close .c_emp;
10, 返回结果集的存储过程
--1,创建一个包,在该包中,定义类型test_sursor, 是个游标
create or replace package testpackage as
type test_cursor is ref cursor;
end tespackage;
--2 创建过程
create or replace procedure sp_pro9(spNo in number, p_cursor out tespackage.test_cursor)
is
begin
open p_cursor for select * from emp where deptno =spno;
end;
java调用返回的是结果集:
CallableStatement cs=conn.prepareCall("{call sp_pro9(?,?)}");//第一个参数是入参数,第二个是游标出参数
cs.setString(1,10);//给第一个? 赋值
//给第二个?赋值
cs.registerOutParameter(2,oracle.jdbc.oracleTypes.CURSOR); //过程的第二个参数为游标输出参数,类型要一致
cs.execute(); //执行
ResultSet rs=(ResultSet)cs.getobject(2); //得到结果集
while(rs.next()){
syso(rs.getInt(1)+' '+rs.getString(2) ); //迭代取出数据,第一列和第二列
}
10,if控制
if v_job='pro' then
update emp set sal=sal+1000 where empno=spNo;
elsif v_job='MAN' then
update emp set sal=sal+500 where empno=spNo;
else
update emp set sal=sal+200 where empno=spNo;
end if;
触发器:create trigger
11.循环:
方式一:
loop
insert into users values(v_num, spname);
exit when v_num=10;--判断是否退出循环,符合条件退出
end loop;
方式二:
while v_num<=20 loop --符合条件才执行
insert into users values(v_num, spname);
v_num:=v_num+1;
end loop;
方式三:
for i in 1..10 loop
insert into users values(v_num, spname);
end loop;
12, goto语句
declare
i int :=-1;
begin
loop
dbms_output.put_line('输出i='||i);
if i=10 then
goto end_loop; --跳转到特定标号处
end if;
i:=i+1;
end loop;
<<end_loop>>
dbms_output.put_line('循环结束');
end;
13, null语句不会执行任何操作,
14,分页算法
--1,创建一个包,在该包中,定义类型test_sursor, 是个游标
create or replace package testpackage as
type test_cursor is ref cursor;
end tespackage;
--2 创建过程
create or replace procedure fenye (
tableName in varchar2, --表名
pagesize in number, --每页显示记录数
pageNow in number, --显示第几页
myrows out number, --总记录数
mypagecount out number,总页数
p_cursor out testpackage.test_cursor --返回的结果集
) is
---定义变量
v_sql varchar2(1000);
v_begin number:=(pageNow-1)*pagesize+1; --计算显示页的第一条记录
v_end number:=pageNow*pagesize; --计算显示页的第二条记录
begin
v_sql:='select * from (select t.* , rownum rn from(select * from '|| tableName||') t where rownum<='|| v_end||' ) where rn >='||v_begin;
open p_cursor for v_sql;
v_sql:='select count(*) from '||tablesName;
execute immediate v_sql into myrows; --表的总记录数
if mod(myrows, pagesize)=0 then --计算总页数
mypageCount := myrows/Pagesize;
else
myPageCount :=myrows/Pagesize+1;
end if;
close p_cursor; --关闭游标
end;
15,case语句
create or replace procedure sp_pro6(spno number) is
v_sal emp.sal%type;
begin
select sal into v_sal from emp where empno=spno;
case
when v_sal <1000 then
update emp set sal=sal+100 where empno=spno;
when v_sal <2000 then
update emp set sal=sal+200 where empno=spno;
end case;
exception
when case_not_found then
dbms_output.put_line('case没有相匹配的');
end;
16例外:
case_not_found case中没有相对应的条件
cursor_already_open 游标已经打开
dup_val_on_index 唯一索引重复插入inser语句
invaild_cursor 从未打开的游标中提取数据,关闭没有打开的游标
invalid_number 输入的数据有误比如100输成LOO
no_data_found 当select中没有返回行
too_many_rows 当select返回超过了一行,返回了多行
zero_divide 当执行3/0会触发该例外,分母不能为0
value_error 赋值操作变量的长度不足以容纳实际数据
自定义例外
create or replace procedure ex_test(spNo number)
is
myex exception; --定义一个自定义例外
begin
update emp set sal=sal+1000 where empno=spNo;
if sql%notfound then --这是表示没有更新成功
raise myex; --触发myex
end if;
exception
when myex then
dbms_output.put_line('没有更新任何用户');
end;
调用:exec ex_test(56);
17,视图view
create or replace view 视图名 as select 语句 [ with read only]只可读不可改
删除视图 : drop view 视图名
eg: create view myview as select * from emp where sal<1000;
18,当语句中包含单引号使用q加分割符号
v_event := q'!Father's day!'; 前面加q其中!为分割符号
v_event :=q'[Mother's day]'; 前面加q其中[]为分割符号
v_event :='Father''s day'; 双单引号
19:存储过程循环
存储过程for循环:
create or replace package body update_payend_status is
procedure updatestatus(mkey varchar2,accountid number)is
v_sumUnits float :=0;
v_flag pglumpsum.flag%type;
v_mkey pglumpsum.mkey%type;
begin
open getPenFlag(mkey);
fetch getPenFlag into v_flag;
close getPenFlag;
open getAllPayendMembers;
loop
fetch getAllPayendMembers into v_mkey,v_accountid;
exit when getAllPayendMembers%NOTFOUND;
addCalc(v_mkey,v_accoutid);
end loop;
close getAllPayendMembers;
end;
END;
20, -----先创建序列,再创建触发器
create sequence SEQ_FIXED_TRADEDATE
minvalue 1
maxvalue 9999999
start with 3
increment by 1
nocache;
--创建触发器
create or replace trigger tg_fixed_Tradedate
before insert on fixed_Tradedate for each row --定义before触发器,监测表fixed_tradedate的插入操作,行级别的触发器
when (new.ID is null)
begin
select SEQ_FIXED_TRADEDATE.nextval into:new.ID from dual;
end;
---删除序列
drop sequence SEQ_FIXED_TRADEDATE;
--创建同义词
create sysnonym client_54,user for fe.user;
--删除同义词
drop sysnonym user;
--授权
grant select ,insert,update,execute on payment_batch_proc to client_54;
--增加对表空间的权限
alter user client_54 quota unlimited on users;