目录: 1、什么是PL/SQL
2、PL/SQL 语法基础
3、PL/SQL 实例
一、过程 实例
二、函数 实例
三、游标的使用 实例
四、动态sql 实例
五、触发器 实例
1、什么是PL/SQL
PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL)。PL/SQL是Oracle数据库对SQL语句的扩展。在普通SQL语句的使用上增加了编程语言的特点,所以PL/SQL就是把数据操作和查询语句组织在PL/SQL代码的过程性单元中,通过逻辑判断、循环等操作实现复杂的功能或者计算的程序语言。
2、PL/SQL 语法基础
参考:Link
3、PL/SQL 实例
一、过程实例
(1)模拟一次 100块钱 的转账
set serveroutput on; --每次会话开始打开这个开关来显示输出信息
declare
v_num number :=0;
begin
update t_account set AResidualAmount = AResidualAmount-100 where anumber=''; v_num:=SQL%rowcount;
if v_num <= 0 then
dbms_output.put_line('201330340106 账户扣款不成功,转账失败!');
return ;
end if; update t_account set AResidualAmount = AResidualAmount+100 where anumber='';
if v_num <= 0 then
dbms_output.put_line('201330340106 账户入款不成功,转账失败!');
rollback;
return;
end if; insert into t_trade_detail
values(SEQ_TRADE_DETAIL.nextval,'',100,sysdate,'','','转出备注');
if v_num <= 0 then
dbms_output.put_line('201330340121 账户扣款明细写入不成功,转账失败!');
rollback;
return;
end if; insert into t_trade_detail
values(SEQ_TRADE_DETAIL.nextval,'',100,sysdate,'','','转入备注'); if v_num <= 0 then
dbms_output.put_line('201330340106 账户入款明细写入不成功,转账失败!');
rollback;
return;
end if; dbms_output.put_line('201330340121 向 201330340106 账户成功!');
commit;
exception
when others then
dbms_output.put_line('转账发生错误:'||SQLERRM);
rollback;
end;
模拟一次100块的转账
(2)根据员工的编号,输出该员工的基本信息(姓名,雇佣日期,薪水,提成比例)
create or replace procedure p_queryemp(i_empid employees.employee_id%type)
as
v_ename varchar(50);
v_date employees.hire_date%type;
v_salary employees.salary%type;
v_commission employees.commission_pct%type; begin
select first_name||' '||last_name ename,hire_date,salary,commission_pct
into v_ename ,v_date,v_salary ,v_commission
from employees where employee_id = i_empid;
dbms_output.put_line(v_ename ||v_date||v_salary ||v_commission);
exception
when no_data_found then
dbms_output.put_line('没有找到员工信息!');
when others then
dbms_output.put_line(sqlerrm);
end;
/
show error; set serveroutput on;
exec p_queryemp(1100);
根据员工的编号,输出该员工的基本信息
二、函数实例
(1)根据商品ID查询商品价格
create or replace function f_queryprice(i_gid t_goods.gid%type) return number
as
v_price number(8,2);
begin
select gprice* nvl(gdiscount,1) into v_price
from t_goods where i_gid=gid;
return v_price; exception
when no_data_found then
return -1;
when others then
dbms_output.put_line(sqlerrm);
return -2; end;
/
show error; set outputserver on;
select f_queryprice('G04001') from dual;
根据商品ID查询商品价格
(2)自动生成插入表的数据ID
create or replace function f_createomid_procure return varchar2
as
v_pmid varchar2(12);
v_num number;
v_max t_main_procure.pmid%type;
begin
v_pmid:='P'||to_char(sysdate,'yymmdd'); select count(pmid) into v_num
from t_main_procure where to_char(sysdate,'yymm')=to_char(pdate,'yymm');
if v_num=0 then
v_pmid := v_pmid||'';
else
select max(pmid) into v_max
from t_main_procure where to_char(sysdate,'yymm')=to_char(pdate,'yymm');
v_pmid :=v_pmid || trim(to_char(to_number(substr(v_max,8,5))+1,''));
end if; return v_pmid;
exception
when others then
dbms_output.put_line(sqlerrm);
return null;
end;
/
show error;
自动生成插入表的数据ID
(3)实现采购单编码规则:Pyymmdd0000N,p160712000001
create or replace function f_createomid return varchar2
as
v_omid varchar2(12);
v_num number;
v_max t_main_order.omid%type;
begin
v_omid:=to_char(sysdate,'yyyymm');
select count(omid) into v_num
from t_main_order where to_char(odate,'yyyymm')=to_char(sysdate,'yyyymm');
if v_num=0 then
v_omid:=v_omid||'';
else
select max(omid) into v_max
from t_main_order where to_char(odate,'yyyymm')=to_char(sysdate,'yyyymm');
v_omid:=v_omid||trim((to_char(to_number(substr(v_max,7,6))+1,'')));
end if;
return v_omid; exception
when others then
return null;
end;
/
show error; insert into t_main_procure values(f_createomid_procure,'',sysdate,null,1,'备注');
select * from t_main_procure;
select * from t_order_items;
实现采购单编码规则
(4)实现输入一个员工编号,返回他应该缴的个人所得税
create or replace function f_tax(i_empid employees.employee_id%type)return number
as
v_sal number;
v_tax number;
v_excess number;
begin
select salary into v_sal
from employees where employee_id = i_empid;
v_excess:=v_sal-3500;
if(v_sal<=0) then v_tax:=0;
elsif(v_sal<=1500) then
v_tax:=v_excess*0.03;
elsif(v_sal<=4500) then
v_tax:=v_excess*0.1-105;
elsif(v_sal<=9000) then
v_tax:=v_excess*0.2-555;
elsif(v_sal<=35000)then
v_tax:=v_excess*0.25-1005;
elsif(v_sal<=55000)then
v_tax:=v_excess*0.3-2755;
elsif(v_sal<=80000)then
v_tax:=v_excess*0.35-5505;
else
v_tax:=v_excess*0.45-13505;
end if;
return v_tax; exception
when others then
return null;
end;
/
show error;
select salary ,f_tax(201) from employees where employee_id=201;
实现输入一个员工编号,返回他应该缴的个人所得税
(5)编写一个程序,实现输入一个员工编号,返回它的工资
create or replace function f_sal(i_empid employees.employee_id%type) return number
as
v_sal number;
begin
select salary into v_sal
from employees where employee_id = i_empid;
return v_sal; exception
when no_data_found then
return -1;
end;
/
show error; select f_sal(100) from dual;
编写一个程序,实现输入一个员工编号,返回它的工资
三、游标的使用实例
for版本
create or replace procedure p_querydepartmentemp(i_depno in employees.department_id%type)
as
v_ename varchar(50);
v_date employees.hire_date%type;
v_salary employees.salary%type;
v_commission employees.commission_pct%type;
cursor cur_emp is select first_name||' '||last_name ename,hire_date,salary,commission_pct
from employees where department_id = i_depno;
v_record_emp cur_emp%rowtype;
begin
for v_record_emp in cur_emp loop
--dbms_output.put_line(v_ename||' ' ||v_date||' '||v_salary ||' '||v_commission);
dbms_output.put_line(v_record_emp.ename||' ' ||v_record_emp.hire_date||' '||v_record_emp.salary ||' '||v_record_emp.commission_pct);
end loop;
exception
when no_data_found then
dbms_output.put_line('没有找到员工信息!');
when others then
dbms_output.put_line(sqlerrm);
end;
/
show error; set serveroutput on;
exec p_querydepartmentemp(50);
游标的使用(for版本)
while版本
create or replace procedure p_querydepartmentemp(i_depno in employees.department_id%type)
as
v_ename varchar(50);
v_date employees.hire_date%type;
v_salary employees.salary%type;
v_commission employees.commission_pct%type;
cursor cur_emp is select first_name||' '||last_name ename,hire_date,salary,commission_pct
from employees where department_id = i_depno;
v_record_emp cur_emp%rowtype;
begin
open cur_emp;
--fetch cur_emp into v_ename ,v_date,v_salary ,v_commission;
fetch cur_emp into v_record_emp;
while(cur_emp%found) loop
--dbms_output.put_line(v_ename||' ' ||v_date||' '||v_salary ||' '||v_commission);
dbms_output.put_line(v_record_emp.ename||' ' ||v_record_emp.hire_date||' '||v_record_emp.salary ||' '||v_record_emp.commission_pct);
fetch cur_emp into v_record_emp;
end loop;
close cur_emp;
exception
when no_data_found then
dbms_output.put_line('没有找到员工信息!');
when others then
dbms_output.put_line(sqlerrm);
end;
/
show error; set serveroutput on;
exec p_querydepartmentemp(7); ---?
游标的使用(while版本)
四、动态sql 实例
(1)在不知不清楚表名,列名的情况下使用删除表的存储过程 (使用 sql 执行 drop 语句 (DDL语句) )
create or replace procedure p_droptable(i_tablename varchar)
as
v_sql varchar2(100);
begin
v_sql:='drop table'||i_tablename;
execute immediate v_sql;
end;
/
show error;
根据表名字删除表
(2)使用动态sql+游标 创建用户
create or replace procedure p_createuser
as
cursor cur_uiid is select uiid from t_user;
v_uiid t_user.uiid%type;
begin
open cur_uiid;
fetch cur_uiid into v_uiid;
while(cur_uiid%found) loop
execute immediate 'create user '|| v_uiid ||' identified by 123';
execute immediate 'grant connect,resource to '||v_uiid;
dbms_output.put_line(v_uiid||'创建成功');
fetch cur_uiid into v_uiid;
end loop;
close cur_uiid;
exception
when others then
dbms_output.put_line(sqlerrm);
end;
/
show error;
使用动态sql+游标 创建用户
五、触发器 实例
触发器:特殊的存储过程,不需要人工调用,在满足触发器的条件是自动触发
操作:针对数据库级:数据库级触发器
针对表对象: 表级触发器
简单视图时可以修改数据,用一个替换的触发器来替代修改视图的语句,替代触发器
实例:
(1)订单明细的 增删改
① 在订单中,当在订单明细里面添加一条明细记录,订单主表的总金额增加
create or replace trigger tr_insertorderitems
after insert on t_order_items
for each row
begin
update t_main_order set oamount= nvl(oamount,0)+ nvl(:new.oprice,0)*nvl(:new.onum,0)
where omid=:new.omid;
end;
/
show error;
订单明细的 增
②当订单的明细记录有删除的时候,订单主表的总金额要减少
create or replace trigger tr_deleteorderitems
after delete on t_order_items
for each row
begin
update t_main_order set oamount= nvl(oamount,0)-nvl(:old.oprice,0)*nvl(:old.onum,0)
where omid = :old.omid;
end;
/
show error;
订单明细的 删
③当订单的明细的数量和单价修改是,订单主表的总金额要发生变化
create or replace trigger tr_updateorderitems
after update on t_order_items
for each row
begin
update t_main_order set oamount= nvl(oamount,0)+
(nvl(:new.oprice,0)*nvl(:new.onum,0)-nvl(:old.oprice,0)*nvl(:old.onum,0))
where omid = :new.omid;
end;
/
show error;
订单明细的 改
测试(1):
insert into t_order_items values('','G04002',f_queryprice('G04002'),2,null);
delete from t_order_items where omid='' and gid='G04002';
update t_order_items set onum=onum-1, oprice=oprice-10 where omid='' and gid='G04001';
对(1)的测试
(2)已经审核的单据不能添加删除明细
create or replace trigger tr_checkinsertorderitems
before insert on t_order_items
for each row
declare
v_state t_main_order.ostate%type;
begin
select ostate into v_state from t_main_order where omid = :new.omid;
if v_state<>'' then
---抛出异常
raise_application_error(-20001,'已经审核的订单无法添加明细!');
end if;
end;
/
show error;
已经审核的单据不能添加删除明细
(3)只要一个商品获得评价为差评,价格就降低一个百分点
create or replace trigger tr_insertevaluation
after insert on t_user_evaluation
for each row
declare
v_etype t_user_evaluation.ueid%type;
begin
if :new.uetype='C' then
update t_goods set gdiscount = nvl(gdiscount,0)*0.99
where gid = :new.gid;
end if;
end;
/
show error; ----测试语句
insert into t_user_evaluation
values(to_char(sysdate,'yymmdd')||trim(to_char(seq_ueid.nextval,'')),'','G04001',sysdate,'C','这东西,烂!');
只要一个商品获得评价为差评,价格就降低一个百分点
提示:如果多个触发器满足:针对同一个对象,同样是before 或者after,同样是行级或者语句级触发器,则不同的操作可以把这些触发器组合在一起
(4)对(1)的改进,将三个对订单详细表的修改集中到一个触发器
create or replace tr_orderitems
after insert or update or delete on t_order_items
for each row
begin
if inserting then elsif deleting then elsif updating then end if;
end;
一个触发器处理多个操作
注意:触发器要注意避免多个触发器导致操作的重复
Oracle——PL/SQL 语句的更多相关文章
-
Oracle PL/SQL语句基础学习笔记(上)
PL/SQL是ORACLE对标准数据库语言的扩展,ORACLE公司已经将PL/SQL整合到ORACLE server和其它工具中了,近几年中很多其它的开发者和DBA開始使用PL/SQL,本文将讲述PL ...
-
Oracle PL/SQL
PL/SQL 简介 PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的编程语言,是对 SQL 的扩展,它支持多种数据类型,如大对象和集合类型,可使用 ...
-
ORACLE PL/SQL编程详解
ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...
-
oracle常用SQL语句(汇总版)
Oracle数据库常用sql语句 ORACLE 常用的SQL语法和数据对象一.数据控制语句 (DML) 部分 1.INSERT (往数据表里插入记录的语句) INSERT INTO 表名(字段名1, ...
-
[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)
原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...
-
ORACLE PL/SQL编程之八:把触发器说透
原文:ORACLE PL/SQL编程之八:把触发器说透 ORACLE PL/SQL编程之八: 把触发器说透 大家一定要评论呀,感谢!光发表就花了我将近一个下午. 本篇主要内容如下: 8.1 触发器类型 ...
-
[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)
原文:[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不殆) [推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/S ...
-
ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)
原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!) 继上篇:ORACLE P ...
-
[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)
原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ...
随机推荐
-
NRF905 无线模块实验
---恢复内容开始--- 采用2440开发板,CON4 不仅包含了很多富余的 GPIO 引脚,还包含了一些其他 CPU 引脚, 如 AD0-AIN3, CLKOUT 等.你所看到的图中的 SPI 接口 ...
-
Fix ";Missing Scripts";
一.Missing Scripts(脚本引用丢失) 请看下面的两张图的Warn(脚本引用丢失),在某些情况下我们会遇到这个警告. 二.解决办法 参考资料 http://unitygems.com/la ...
-
java SE (java Standard Edition)
14.10.22 学习java SE的Object: -------------------------------------15.11.18----
-
@Autowired获取配置文件中被注入实例的两种方式
一.说明 二.那么在JavaBean中如何通过@Autowired获取该实例呢?有两种方式: 1.直接获取 @RunWith(SpringJUnit4ClassRunner.class) @Conte ...
-
怎么加 一个 hyperlink 到 e-mail template for CRM
Recently I had a client inquire as to how one would insert a hyperlink into a CRM email template. Wh ...
-
忽略git中不需要进行版本管理的文件
在git中我们提交项目的时候有很多东西是不需要进行版本管理的,因此我们需要忽略掉. 虽然在github2.0的windows客户端提供了工具,但是这个工具并不是想象中的那么好用. 在上面点右键出现的D ...
-
MVC MVC 路由详解
在项目中我们引用了System.Web.Routing; Routing的作用: 确定Controller 确定Action 确定其他参数 根据识别出来的数据, 将请求传递给Controller和 ...
-
01 Android修改新建虚拟机存放的位置
创建的Android虚拟机(即AVD)的位置是在C盘的当前用户文件夹下(C:\Users\用户名\.android\avd) 这一默认设置不怎么好,特别是C盘空间吃紧的话. 这里提供2个解决办法(分2 ...
-
python3.6 连接mysql数据库问题
最近有个项目欲安装MySQL-python/1.2.5一直失败. 环境: win7 python3.6.2 报错信息如下: Creating library build\temp.win32-3.6\ ...
-
静默安装/ 普通安装与root权限获取相关
静默安装 有时候使用第三方的插件时我们需要静默安装其提供的apk包,静默安装时我们需要获取root权限,如下代码 Process process = Runtime.getRuntime().exec ...