Oracle基礎進階
PL/SQL
是Oracle對sql語言的過程化擴展,指在sql命令語言中增加了過程處理語句,是sql語言具有過程處理能力.
語法:
[declare
--聲明變量
]
begin
--邏輯代碼
[exception
--異常處理
]
變量:
聲明變量的語法:變量名 類型(長度)
變量賦值的語法:變量名:=變量值
例如
declare v_price number(10,2);--單價 v_usenum number;--水費數字 v_usenum2 number(10,2);--噸數 v_money number(10,2);--總價 begin v_price:=2.45; v_usenum:=3306; v_usenum2:=round(v_usenum/1000,2); v_money:=v_usenum2*v_price; DBMS_output.put_line(‘總價:‘||v_money); end;
對於變量的賦值,還 可以用:select into方式賦值 select 列名 into 變量名 from 表名 where 條件
但是這種方式的結果必須是一條記錄,有多條記錄和沒有記錄都會報錯
這裏就可以吧上面的水費的數字改成從已經有的表中查找出來
select usernum into v_usenum fromt_account where owneruuid=1;
屬性類型分為引用型和記錄型,首先介紹引用型
%type(引用型):引用某表某列的字段類型
還是上面的例子,水費數字的number可以改為指定表中指定列的引用型類型
v_usenum t_account.usenum%type;
%rowtype(記錄型):表示某個表的行記錄類型
依舊上面的例子,水費數字等數據可以被替代為:
v_account t_account%rowtype;
這個賦值可以看做是為一個對象賦值一行數據,而這個對象在這裏就是v_account
賦值語句:
select * into v_account fromt_account where owneruuid = 1;
這樣在後面使用的時候直接點調用裏面需要的數據
比如要調用水費數字:
v_account.usenum;這就得到了水費數字在原表中的數據
異常:
在運行程序時出現的錯誤叫做異常
發生異常後,語句將停止執行,控制權轉移到PL/SQL塊的異常處理部分.
在這裏介紹兩個預定義異常,預定義異常就是當PL/SQL程序違反Oracle規則或超越系統限制時隱式引發
首先介紹第一個:
NO_DATA_FOUND:使用select into未返回行
TOO_MANY_ROWS:執行select into時,結果集超過一行
exception
when 異常類型 then
異常處理邏輯
還是以上面的為例子,模擬在給水費數字賦值的時候,select into未返回行
... begin exception when NO_DATA_FOUND then dbms_output.put_line(‘沒有返回數據‘); end; 如果在再此基礎上添加一個超過結果集的異常,那麽 ... begin exception when NO_DATA_FOUND then dbms_output.put_line(‘沒有返回數據‘); when TOO_MANY_ROWS then dbms_output.put_line(‘返回信息過多‘); end;
條件判斷
基本語法1:
if 條件 then
業務邏輯
end if;
基本語法2:
if 條件 then
業務邏輯
else
業務邏輯
end if;
基本語法3:
if 條件 then
業務邏輯
elsif 條件 then
業務邏輯
else
業務邏輯
end if;
下面是一個前面綜合的完整列子:
5 噸以下 2.45 元/噸 5 噸到 10 噸部分 3.45 元/噸 ,超過 10 噸部分 4.45 ,根據使用水費的量來計算階梯水費。
declare v_price1 number(10,2);-- 不足 5 噸的單價 v_price2 number(10,2);-- 超過 5 噸不足 10 噸單價 v_price3 number(10,2);-- 超過 10 噸單價 v_account T_ACCOUNT%ROWTYPE;-- 記錄型 v_usenum2 number(10,2);-- 使用噸數 v_money number(10,2);-- 水費金額 begin -- 對單價進行賦值 v_price1:=2.45; v_price2:=3.45; v_price3:=4.45; -- 給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); -- 計算金額 ( 階梯水費 ) if v_usenum2<=5 then-- 第一個階梯 v_money:=v_price1*v_usenum2; elsif v_usenum2>5 and v_usenum2<=10 then -- 第二個階梯 v_money:=v_price1*5 + v_price2*( v_usenum2-5); else -- 第三個階梯 v_money:=v_price1*5 +v_price2*5 + v_price3*( v_usenum2-10 ); end if; DBMS_OUTPUT.put_line(‘金額‘ || v_money); exception when NO_DATA_FOUND then DBMS_OUTPUT.put_line(‘沒有找到數據‘); when TOO_MANY_ROWS then DBMS_OUTPUT.put_line(‘返回的數據有多行‘); end;
循環:
下面是用1-100的循環例子解釋三種不同的循環
無條件循環(語法):
loop
-- 循環語句
end loop;
第一種解法:
declare v_num number:=1; begin loop dbms_output.put_line(v_num); v_num:=v_num+1; exit when v_num>100; end loop; end ;
條件循環(語法):
while 條件
loop
end loop;
第二種解法:
declare v_num number:=1; begin while v_num<=100 loop dbms_output.put_line(v_num); v_num:=v_num+1; end loop; end ;
for循環(語法):
for 變量 in 起始值..終止值
loop
end loop;
第三種解法:
begin for v_num in 1..100 loop dbms_output.put_line(v_num); end loop; end;
遊標:
遊標是系統為用戶開設的一個數據緩沖區,存放sql語句的執行結果,可以把遊標理解為PL/SQL中的結果集
聲明遊標的語法:
cursor 遊標名稱 is SQL 語句;
使用遊標的語法:
open 遊標名稱
loop
fetch 遊標名稱 into 變量
exit when 遊標名稱%notfound
end loop;
close 遊標名稱;
下面的例子使用scott用戶操作Oracle中的默認emp表
declare --定義遊標 cursor cemp is select ename,sal from emp; --定義變量 vename emp.ename%type; vsal emp.sal%type; begin --打開遊標,這時遊標位於第一條記錄之前 open cemp; --循環 loop --向下移動遊標一次 fetch cemp into vename,vsal; --退出循環,當遊標下移一次後,找不到記錄時,則退出循環 exit when cemp%notfound; --輸出結果 dbms_output.put_line(vename||‘--------‘||vsal); end loop; --關閉遊標 close cemp; end;
存儲函數
存儲函數就是自定義函數,可以接收一個或多個參數,返回一個結果,在函數中我們可以使用P/SQL進行邏輯的處理
創建或修改存儲過程的語法:
CREATE [ OR REPLACE ] FUNCTION 函數名稱 (參數名稱 參數類型, 參數名稱 參數類型, ...) RETURN 結果變量數據類型 IS 變量聲明部分; BEGIN 邏輯部分; RETURN 結果變量; [EXCEPTION 異常處理部分] END;
下面幾個例子:
創建存儲函數,根據地質id查詢地址名稱
create function fn_getaddress(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;
測試函數:
select fn_getaddress(3) from dual;
存儲過程
存儲過程是被命名的PL/SQL塊,存儲於數據庫中,是數據庫對象的一種.
存儲過程語法如下:
CREATE [ OR REPLACE ] PROCEDURE 存儲過程名稱 (參數名 類型, 參數名 類型, 參數名 類型) IS|AS 變量聲明部分; BEGIN 邏輯部分 [EXCEPTION 異常處理部分] END;
過程參數的三種模式:
IN 傳入參數(默認)
OUT 傳出參數,主要用於返回程序運行結果
IN OUT 傳入傳出參數
帶傳出參數的存儲過程
-- 增加業主信息序列 create sequence seq_owners; create or replace procedure pro_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( v_id,v_name,v_addressid,v_housenumber,v_watermete r,sysdate,v_type ); commit; end;
PL/SQL 調用該存儲過程:
declare v_id number;-- 定義傳出參數的變量 begin pro_owners_add(‘王旺旺‘,1,‘922-3‘,‘133-7‘,1,v_id); DBMS_OUTPUT.put_line(‘增加成功,ID:‘||v_id); end;
觸發器
數據庫觸發器是一個與表相關聯的,存儲的PL/SQL程序,每當一個特定的數據操作語句(insert,update,delete)在
指定的表上發出時,Oracle自動地執行觸發器中定義的語句序列
觸發器分為前置觸發器(before)和後置觸發器(after)
創建觸發器的語法:
CREATE [or REPLACE] TRIGGER 觸發器名 BEFORE | AFTER [DELETE ][[or] INSERT] [[or]UPDATE [OF 列名]] ON 表名 [FOR EACH ROW ][WHEN(條件) ] declare …… begin PLSQL 塊 End ;
在觸發器中觸發語句與偽記錄變量的值
觸發語句 :old :new Insert 所有字段都是空(null) 將要插入的數據 Update 更新以前該行的值 更新後的值 delete 刪除以前該行的值 所有字段都是空(null)
前置觸發器案例:
創建語句級觸發器insertEmpTrigger,當對表【emp】進行增加【insert】操作前【before】,顯示"hello world"
create or replace tirgger insertEmpTrigger before insert on emp begin dbms_output.put_line(‘hello wordl‘); end;
Oracle基礎進階