半小時帶你了解 PL/SQL

簡介:PL/SQL是是甲骨文公司開發,嵌入在Oracle數據庫中的編程語言。

基礎

  • 塊結構
    • declare 聲明部分 – 所有變量,游標,子程序,和其他元素
    • begin - end ; – 程序主體,可執行命令
  • 常見符號解釋:
符號 含義
|| 字符串連接符
:+ 賦值運算符
% 獲得相同的數據類型
= 相等運算符
  • 變量的常見類型:
類型 含義
varchar2 可變長字符串
int 整數類型
number (precision,scale) precision表示數字中的有效位,如果沒有指定precision的話,oracle將使用38作為精度, 如果scale大于零,表示數字精度到小數點右邊的位數;scale默認設置為0;如果scale小于零,oracle將把該數字取舍到小數點左邊的指定位數
clob 用于存儲字符大塊數據在數據庫中 大小為 8 - 128 TB
date 日期和時間
  • 數組 TYPE varray_type_name IS VARRAY(n) OF element_type
DECLARE
    type namesarray IS VARRAY(5) OF VARCHAR2(10);
    type grades IS VARRAY(5) OF INTEGER;
    names namesarray; --拿到數組的引用,下面就可以變長使用該數組
    marks grades;
    total integer;
BEGIN
    names := namesarray('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
    marks:= grades(98, 97, 78, 87, 92);
    total := names.count; --求數組的長度
    dbms_output.put_line('Total '|| total || ' Students');
    FOR i in 1 .. total LOOP
        dbms_output.put_line('Student: ' || names(i) || ' Marks: ' || marks(i));
    END LOOP;
END;
  • 全局變量與局部變量
DECLARE
    -- Global variables
    num1 number := 95;
BEGIN
    DECLARE
        -- Local variables
        num1 number := 195;
    BEGIN
        
    END;
END;
  • 常量
PI constant number := 3.14;
  • SELECT INTO 取值出來使用: SELECT 表中變量 INTO 定義變量 FROM XXX
declare
  c_id customers.id%type := 1;
  c_name customers.name%type;
  c_addr customers.address%type;
  c_sal customers.salary%type;
begin
  select name,address,salary into c_name,c_addr,c_sal from customers where id = c_id;
  dbms_output.put_line('Customer '||c_name||' from '||c_addr||' earns '||c_sal);
end;
  • 控制語句
    1. IF 語句:if 使用 end if 結束
DECLARE
    a number(3) := 100;
BEGIN
    IF ( a = 10 ) THEN
        dbms_output.put_line('Value of a is 10' );
    ELSIF ( a = 20 ) THEN
        dbms_output.put_line('Value of a is 20' );
    ELSE
        dbms_output.put_line('None of the values is matching');
    END IF;
    dbms_output.put_line('Exact value of a is: '|| a );
END;

?2. CASE語句: 以end case 結束

declare
  grade char(1) := 'A';
begin
  case grade
    when 'A' then dbms_output.put_line('A');
    when 'B' then dbms_output.put_line('B');
    else dbms_output.put_line('NO');
  end case;
end;
  • 循環控制語句
    ?1. LOOP :已END LOOP結束
DECLARE
    x number := 10;
BEGIN
    LOOP
        dbms_output.put_line(x);
        x := x + 10;
        IF x > 50 THEN
            exit;
        END IF;
    END LOOP;
    -- after exit, control resumes here
    dbms_output.put_line('After Exit x is: ' || x);
END;

?2. WHILE: 已END LOOP結束

DECLARE
    a number(2) := 10;
BEGIN
    WHILE a < 20 LOOP
        dbms_output.put_line('value of a: ' || a);
        a := a + 1;
    END LOOP;
END;
  1. FOR: 已END LOOP結束
DECLARE
    a number(2);
BEGIN
    FOR a in 10 .. 20 LOOP   -- 10 .. 20 表示10-20 全包含
        dbms_output.put_line('value of a: ' || a);
    END LOOP;
END;

進階 (進步進階無所謂半小時就看完了)

  • 兩種子程序:
    ?參數 in :入參, out : 返回值, in out :入參且是返回值
create PROCEDURE squareNum(x IN OUT number) IS
BEGIN
    x := x * x;
END;

? 1. 函數:這些子程序返回一個值,主要用于計算并返回一個值。
??1.1. 創建函數

CREATE [OR REPLACE] FUNCTION function_name
[(parameter_name [IN | OUT | IN OUT] type [, ...])] RETURN return_datatype
    {IS | AS}
BEGIN
    < function_body >
     RETURN XXX;
END [function_name];
  1. 過程:這些子程序沒有直接返回值,主要用于執行操作。
    2.1. 創建過程
Create PROCEDURE findMin(x IN number, y IN number, z OUT number) IS
BEGIN
    IF x < y THEN
        z:= x;
    ELSE
        z:= y;
    END IF;
END;

?2.2. 銷毀過程

drop procedure procedure_name;
  • 游標
    1. 隱式游標
      DML操作和單行SELECT語句會使用隱式游標,它們是:
      ?* 插入操作:INSERT。
      ?* 更新操作:UPDATE。
      ?* 刪除操作:DELETE。
      ?* 單行查詢操作:SELECT ... INTO ...。
      當系統使用一個隱式游標時,可以通過隱式游標的屬性來了解操作的狀態和結果,進而控制程序的流程。隱式游標可以使用名字SQL來訪問,但要注意,通過SQL游標名總是只能訪問前一個DML操作或單行SELECT操作的游標屬性。所以通常在剛剛執行完操作之后,立即使用SQL游標名來訪問屬性。游標的屬性有四種,如下所示:

??? * sql%found (布爾類型,默認值為null)INSERT、UPDATE、DELETE 成功返回TRUE

??? * sql%notfound(布爾類型,默認值為null)INSERT、UPDATE、DELETE 不成功返回TRUE

??? * sql%rowcount(數值類型默認值為0)返回INSERT、UPDATE、DELETE 影響的行數

??? * sql%isopen(布爾類型)隱式游標返回FALSE,
?2. 顯式游標
? * 聲明游標 cursor c_customer is select * from customers;
?? * 打開游標 open c_customer;
?? * 獲取游標 fetch c_customers into c_addr,c_name,c_salary;
?? * 關閉游標 close c_customers;

declare  c_id customers.id%type;  
    c_name customers.name%type;  
    c_addr customers.address%type;   
    cursor c_customers is select id,name,address from customers;
begin  
    open c_customers;  
    loop    
        fetch c_customers into c_id,c_name,c_addr;    
        exit when c_customers%notfound;    
        dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);  
    end loop;  
    close c_customers;
end;
  • 異常處理
    • 異常聲明 : exception_name exception;
    • 拋出異常 : raise exception_name;
    • 捕獲異常 : when exception_name then…
DECLARE
   c_id customers.id%type := &c_id; -- 接收用戶輸入的值,運行的時候會彈出一個輸入框。
   c_name  customers.name%type;
   c_addr customers.address%type;

   -- user defined exception
   ex_invalid_id  EXCEPTION;
BEGIN
   IF c_id <= 0 THEN
      RAISE ex_invalid_id;
   ELSE
      SELECT  name, address INTO  c_name, c_addr
      FROM customers
      WHERE id = c_id;

      DBMS_OUTPUT.PUT_LINE ('Name: '||  c_name);
      DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);
   END IF;
EXCEPTION
   WHEN ex_invalid_id THEN
      dbms_output.put_line('ID must be greater than zero!');
   WHEN no_data_found THEN
      dbms_output.put_line('No such customer!');
   WHEN others THEN
      dbms_output.put_line('Error!');
END;

TIPS

  • dbms_output.put_line() 輸出日志
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370