PL/SQL(Procedure Language/SQL)
Oracle 對 sql 語言的過程化擴展,指在 SQL 命令語言中增加了過程處理語句(如分支、循環(huán)等),使 SQL 語言具有過程處理能力。
--變量賦值
- 變量名 類型(長度);
- 變量名:=變量值
declare
v1 number(10,2);
v2 number;
v3 number(10,2);
v4 number(10,2);
begin
v1:=2.45;--單價賦值
v2:=9213;--水費字?jǐn)?shù)
v3:=round( v2/1000,2);--噸數(shù)
v4:=v1*v3;--金額
DBMS_output.put_line('用水量'||v1);
DBMS_OUTPUT.put_line('金額:'||v4);
end;
```sql
#### --select 列名 into 變量名
- select 列名 into 變量名 from 表名 where 條件
``` sql
declare
v1 number(10,2);
v2 number;
v3 number(10,2);
v4 number(10,2);
vp number;
vc number;
begin
v1:=2.45;--單價賦值
select t.usenum,t.num0,t.num1 into v2,vp,vc
from t_account t
where year='2012' and month='01' and t.owneruuid=1;
v3:=round( v2/1000,2);--噸數(shù)
v4:=v1*v3;--金額
DBMS_output.put_line('用水量'||v2);
DBMS_OUTPUT.put_line('金額:'||v4);
DBMS_OUTPUT.put_line('上月表數(shù):'||vp);
DBMS_OUTPUT.put_line('本月表數(shù):'||vc);
end;
--屬性類型 (引用型 表名.列名%type 表名%rowtype)
declare
v_price number(10,2);--單價
v_usenum2 t_account.usenum%type;--噸數(shù)
v_money number(10,2);--金額
v_account t_account%rowtype;--臺賬行記錄類型
begin
v_price:=2.45;--單價賦值
--從數(shù)據(jù)庫中提取一行數(shù)據(jù)賦值給v_account
select * into v_account from t_account
where year='2012' and month='01' and owneruuid=1;
v_usenum2:=round( v_account.usenum/1000,2);--噸數(shù)
v_money:=v_price*v_usenum2;--金額
DBMS_OUTPUT.put_line('字?jǐn)?shù):'||v_account.usenum||'金額:'||v_money);
end;
--異常處理exception
declare
v_price number(10,2);--單價
v_usenum2 number(10,2);--噸數(shù)
v_money number(10,2);--金額
v_account t_account%rowtype;--臺賬行記錄類型
begin
v_price:=2.45;--單價賦值
--從數(shù)據(jù)庫中提取
select * into v_account from t_account
where year='2012' and month='01' ;
v_usenum2:=round( v_account.usenum/1000,2);--噸數(shù)
v_money:=v_price*v_usenum2;--金額
DBMS_OUTPUT.put_line('字?jǐn)?shù):'||v_account.usenum||'金額:'||v_money);
exception
when no_data_found then
DBMS_OUTPUT.put_line('沒有找到賬務(wù)數(shù)據(jù)');
when too_many_rows then
DBMS_OUTPUT.put_line('返回多行賬務(wù)數(shù)據(jù)');
end;
-- 條件判斷(主要中間分支是elsif不是else if)
-- 階梯水價
declare
p1 number(10,2);
p2 number(10,2);
p3 number(10,2);
v_acc T_ACCOUNT%ROWTYPE;
v_u2 number(10,2);
v_m number(10,2);
begin
p1:=2.45;
p2:=3.45;
p3:=4.45;
select * into v_acc from t_Account where year='2012' and month='01' and owneruuid=1;
v_u2:=round(v_acc.usenum/1000,2);
if v_u2<=5 then
v_m:=v_u2*p1;
elsif v_u2>5 and v_u2<=10 then
v_m:=p1*5+(v_u2-5)*p2;
else
v_m:=p1*5+p2*5+(v_u2-10)*p3;
end if;
DBMS_OUTPUT.put_line('噸數(shù):'||v_u2||'金額:'||v_m||'上月字?jǐn)?shù): '||v_acc.num0||'本月字?jǐn)?shù)'||v_acc.num1);
end;
-- 循環(huán)
--loop
declare
p1 number:=1;
begin
loop
dbms_output.put_line(p1);
p1:=p1+1;
exit when p1>100;
end loop;
end;
--while
declare
p1 number:=1;
begin
while p1<=100
loop
dbms_output.put_line(p1);
p1:=p1+1;
end loop;
end;
---for
begin
for p1 in 1..100
loop
dbms_output.put_line(p1);
end loop;
end;
--游標(biāo) 數(shù)據(jù)緩沖區(qū),存放 SQL 語句的執(zhí)行結(jié)果
定義:cursor 游標(biāo)名稱 is SQL 語句;
使用:
open 游標(biāo)名稱
loop
fetch 游標(biāo)名稱 into 變量
exit when 游標(biāo)名稱%notfound
end loop;
close 游標(biāo)名稱
--一般提取
declare
v_p t_Pricetable%rowtype;
--定義游標(biāo)
cursor cur_p(v_o_typeid number) is
select * from t_Pricetable t where t.ownertypeid=v_o_typeid;
begin
--打開游標(biāo)
open cur_p(2);
--循環(huán)提取游標(biāo)到變量
loop
fetch cur_p into v_p;
exit when cur_p%notfound;
dbms_output.put_line('價格:'||v_p.price ||'噸位:'||v_p.minnum||'-'||v_p.maxnum );
end loop;
close cur_p;
end;
--fro循環(huán)提取 無需打開游標(biāo) 關(guān)閉游標(biāo) 循環(huán)游標(biāo) 提取游標(biāo)
declare
--定義游標(biāo)
cursor cur_p(v_o_typeid number) is
select * from t_Pricetable t where t.ownertypeid=v_o_typeid;
begin
--循環(huán)提取游標(biāo)到變量
for v_p in cur_p(2)
loop
dbms_output.put_line('價格:'||v_p.price ||'噸位:'||v_p.minnum||'-'||v_p.maxnum );
end loop;
end;
存儲函數(shù)
語法結(jié)構(gòu):
CREATE [ OR REPLACE ] FUNCTION 函數(shù)名稱
(參數(shù)名稱 參數(shù)類型, 參數(shù)名稱 參數(shù)類型, ...)
RETURN 結(jié)果變量數(shù)據(jù)類型
IS
變量聲明部分;
BEGIN
邏輯部分;
RETURN 結(jié)果變量;
[EXCEPTION
異常處理部分]
END;
-- 根據(jù)地址 ID 查詢地址名稱
create or replace function fn_getadd(v_id number)
return varchar2
is
v_name varchar2(30);
begin
select name into v_name from t_address where id=v_id;
return v_name;
end;
--查詢業(yè)主 ID,業(yè)主名稱,業(yè)主地址,業(yè)主地址使用剛才我們創(chuàng)建的函數(shù)
select id 編號,name 業(yè)主名稱,fn_getadd(addressid) 地址
from t_owners;
存儲過程
被命名的 PL/SQL 塊,存儲于數(shù)據(jù)庫中,可以調(diào)用存儲過程,執(zhí)行相應(yīng)的邏輯
區(qū)別:
- 存儲函數(shù)中有返回值,且必須返回;而存儲過程沒有返回值,可以通過
傳出參數(shù)返回多個值。 - 存儲函數(shù)可以在 select 語句中直接使用,而存儲過程不能。過程多數(shù)是
被應(yīng)用程序所調(diào)用。 - 存儲函數(shù)一般都是封裝一個查詢結(jié)果,而存儲過程一般都封裝一段事務(wù)
代碼.
語法
CREATE [ OR REPLACE ] PROCEDURE 存儲過程名稱
(參數(shù)名 類型, 參數(shù)名 類型, 參數(shù)名 類型)
IS|AS
變量聲明部分;
BEGIN
邏輯部分
[EXCEPTION
異常處理部分]
END;
--增加業(yè)主信息的存儲過程
create or replace procedure p_owners_add(
v_name varchar2,
v_addressid number,
v_housenumber varchar2,
v_watermeter varchar2,
v_type number
) is
begin
insert into T_OWNERS
values( seq_owners.nextval,v_name,v_addressid,v_housenumber,v_watermeter,sysdate,v_type );
commit;
end;
--調(diào)用
call p_owners_add('趙偉',1,'999-3','132-7',1);
select * from T_OWNERS;
- 帶傳出參數(shù)的存儲過程
--添加業(yè)主信息,傳出參數(shù)為新增業(yè)主的 ID
create or replace procedure p_owners_add(
v_name varchar2,
v_addressid number,
v_housenumber varchar2,
v_watermeter varchar2,
v_type number,
v_id out number
) is
begin
select seq_owners.nextval into v_id from dual;
insert into T_OWNERS
values( seq_owners.nextval,v_name,v_addressid,v_housenumber,v_watermeter,sysdate,v_type );
commit;
end;
--調(diào)用
declare
v_id number;
begin
p_owners_add('張偉',1,'9-3','132-8',1,v_id);
dbms_output.put_line('增加成功,ID:'||v_id);
end;
存儲過程綜合案例:
--增加業(yè)主信息時,同時在賬務(wù)表(account)增加一條記錄,
--年份與月份為當(dāng)前日期的年月,初始值(num0)為 0,其它字段信息(區(qū)域)與 t_owners表一致
create or replace procedure p_owners_account_add(
v_name varchar2,
v_addressid number,
v_housenumber varchar2,
v_watermeter varchar2,
v_type number,
v_uid out number
) is
v_year char(4);
v_mount char(2);
v_area number;
begin
select seq_owners.nextval into v_uid from dual;
v_year:=to_char(sysdate,'yyyy');
v_mount:=to_char(sysdate,'mm');
select areaid into v_area from t_address where id=v_addressid;
--增加業(yè)主
insert into T_OWNERS
values( seq_owners.nextval,v_name,v_addressid,v_housenumber,v_watermeter,sysdate,v_type );
--增加賬務(wù)
insert into t_account(id,owneruuid,ownertype,areaid,year,month,num0)
values
(seq_account.nextval,v_uid,v_type,v_area,v_year,v_mount,0);
commit;
exception
when NO_DATA_FOUND then
v_uid:=-1;
rollback;
end;
--調(diào)用
declare
v_id number;
begin
p_owners_account_add('張偉',1,'9-3','132-8',1,v_id);
dbms_output.put_line('增加成功,ID:'||v_id);
end;