/*
存储过程的优点:
模块化:将程序分解为逻辑模块
可重用性:可以被任意数目的程序调用
可维护性:简化维护操作
安全性:通过设置权限,使数据更安全
执行效率较高
语法:
CREATE [OR REPLACE] PROCEDURE
<procedure name> [(<parameter list>)]
IS|AS --变量的声明部分
<local variable declaration>
BEGIN
<executable statements> --业务
[EXCEPTION --异常处理
<exception handlers>]
END;
*/
create or replace procedure pro1
is
v_hello varchar2(20):='hello,xasxt!';
begin
dbms_output.put_line(v_hello);
end;
/*
调用存储过程的方式:
1.execute 存储过程名称(sqlplus中)
eg: execute pro1();
2.call 存储过程名称(sqlplus中)
eg: call pro1();
3.使用程序块调用
begin
存储过程名称
end;
/
*/
begin
pro1();
end;
;
--带参数的存储过程
/*
IN:用于接受调用程序的值
OUT:用于向调用程序返回值
IN OUT:用于接受调用程序的值,并向调用程序返回更新的值
*/
create or replace procedure pro3(emp_no number)
is
v_name varchar2(20);
begin
select ename into v_name from emp where empno=emp_no;
dbms_output.put_line('名称:'||v_name);
exception when NO_DATA_FOUND then
dbms_output.put_line('没有找到雇员信息..');
end;
--调用带参的存储过程
begin
pro3(7656);
end;
--既有输入参数又有输出参数(接受返回值)
create or replace procedure pro4(emp_no in number,emp_sal out number)
is
v_name varchar2(20);
begin
select ename,sal into v_name,emp_sal from emp where empno=emp_no;
dbms_output.put_line('名称:'||v_name);
exception when NO_DATA_FOUND then
dbms_output.put_line('没有找到雇员信息..');
end;
-- 调用
declare
emp_no number:=7934;
emp_sal number;--接收返回值
begin
pro4(emp_no,emp_sal);
dbms_output.put_line('out:....'||emp_sal);
end;
create table t(
id number primary key,
cardnum varchar2(50)not null unique,
balance number(8)
);
insert into t values(1,'01','800');
insert into t values(2,'02','200');
select * from t;
create or replace procedure tranfer(u1 in varchar2,u2 in varchar2,money in number)
is m number;
begin select balance into m from t where cardnum=u1;
if(m-money)>0 then
update t set balance=balance-money where cardnum=u1;
update t set balance=balance-money where cardnum=u1;
update t set balance=balance+money where cardnum=u2;
commit;
else
dbms_output.put_line('余额不足');
end if;
end;
begin
tranfer('01','02',100);
dbms_output.put_line('转账成功');
end;
---根据分页单位算出指定表的总页数
create or replace procedure pro5(tableName in varchar2,pagesize in number,totalnum out number)
is
v_totalpages number;
v_sql varchar2(200);
begin
v_sql:='select count(1) from '||tableName;
--执行动态的sql语句
execute immediate v_sql into v_totalpages;
dbms_output.put_line('v_totalpages-->'||v_totalpages);
if mod(v_totalpages,pagesize)=0 then
totalnum:=v_totalpages/pagesize;
else
totalnum:=ceil(v_totalpages/pagesize);
end if;
end;
--执行
declare totalnum number;
begin
pro5('emp',3,totalnum);
dbms_output.put_line('总页数--》'||totalnum);
end;
触发器
语法:
CREATE [OR REPLACE] TRIGGER 触发器名 触发时间 触发事件
ON表名/视图名
[FOR EACH ROW] //加上FOR EACH ROW 即为行级触发器,不加时为语句级触发器
BEGIN
pl/sql语句
END;
举例:
create table t_post(
id number primary key,
pcontent varchar2(255)
)
create table t_comment(
tid number primary key,
tcontent varchar2(255),
pid number references t_post(id)
)
insert into t_post values(1,'中秋');
insert into t_comment values(1,'中秋快乐',1)
create or replace trigger delete_post before delete
on t_post
FOR EACH ROW
begin
delete from t_comment where pid=:old.id;
end;
--测试前置删除触发器
delete from t_post where id=1;
create table t_users(
id number primary key,
name varchar2(30) not null,
pwd varchar2(30)
);
create table user_temp as (select id,name from t_users where 1=2)
---insert后置触发器
create or replace trigger insert_user after insert
on t_users
for each row
begin
insert into user_temp values(:new.id,:new.name);
end;
insert into t_users values(1,'tom','888888');
select * from user_temp;