1. 程式人生 > >Oracle基礎進階

Oracle基礎進階

行程 sysdate create upd add 三種模式 數據庫對象 hello 輸出

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 from
t_account where owneruuid=1;

屬性類型分為引用型和記錄型,首先介紹引用型
  %type(引用型):引用某表某列的字段類型
還是上面的例子,水費數字的number可以改為指定表中指定列的引用型類型

v_usenum t_account.usenum%type;

%rowtype(記錄型):表示某個表的行記錄類型
依舊上面的例子,水費數字等數據可以被替代為:

v_account t_account%rowtype;

這個賦值可以看做是為一個對象賦值一行數據,而這個對象在這裏就是v_account

賦值語句:

select * into v_account from
t_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基礎進階