[DECLARE
declarations] --聲明部分定義變量、游標和自定義異常
BEGIN
executable statements --包含 SQL 和 PL/SQL 語句的可執行部分
[EXCEPTION
handlers] --指定出現錯誤時需要執行的操作
END;
DECLARE
qty_on_hand NUMBER(5); --聲明部分定義變量、游標和自定義異常
BEGIN --begin到end 包含 SQL 和 PL/SQL 語句的可執行部分
SELECT quantity INTO qty_on_hand
FROM Products
WHERE product = '芭比娃娃'
FOR UPDATE OF quantity;
IF qty_on_hand > 0 THEN
UPDATE Products SET quantity = quantity + 1
WHERE product = '芭比娃娃';
INSERT INTO purchase_record
VALUES ('已購買芭比娃娃', SYSDATE);
END IF;
COMMIT;
EXCEPTION /* 異常處理語句 */ --指定出現錯誤時需要執行的操作
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('出錯:'|| SQLERRM);
END;
identifier [CONSTANT] datatype [NOT NULL]
[:= | DEFAULT expr];
給變量賦值有兩種方法: 1.使用賦值語句 := 2.使用 SELECT INTO 語句
DECLARE icode VARCHAR2(6); p_catg VARCHAR2(20); p_rate NUMBER; c_rate CONSTANT NUMBER := 0.10; BEGIN ... icode := 'i205'; SELECT p_category, itemrate * c_rate INTO p_catg, p_rate FROM itemfile WHERE itemcode = icode; ... END;
指定數值的存儲格式
PL/SQL 的數據類型與 SQL數據類型的比較
數據類型
SQL類型
PL/SQL類型
CHAR
1~2000
1~32767
LONG
1~2GB
1~32760
LONG RAW
1~2GB
1~32760
RAW
1~2000
1~32767
VARCHAR2
1~4000
1~32767
SET SERVEROUTPUT ON DECLARE clob_var CLOB; amount INTEGER; offset INTEGER; output_var VARCHAR2(100); BEGIN SELECT chapter_text INTO clob_var --從表中選擇 CLOB 定位符到 clob_var變量中 FROM my_book_text WHERE chapter_id=5; amount := 24; -- 要讀取的字符數 offset := 1; -- 起始位置 DBMS_LOB.READ(clob_var,amount,offset,output_var); --從CLOB數據中讀取24個字符存儲到 output_var 變量中 DBMS_OUTPUT.PUT_LINE(output_var); --顯示讀到的信息 END;
icode itemfile.itemcode%TYPE; emp_rec scott.emp%ROWTYPE;
關系運算符
說明
=
比較兩個變量是否相等,如果值相當,則返回 True
<>, !=
比較兩個變量,如果不相等,則返回 True
<
比較兩個變量,檢查值 1 是否小於值 2
>
比較兩個變量,檢查值 1 是否大於 值 2
<=
比較兩個變量,檢查變量 1 是否小於等於變量 2
>=
比較兩個變量,檢查變量 1 是否大於等於變量 2
布爾表達式的結果為TRUE、FALSE或NULL,通常由邏輯運算符AND、OR和NOT連接。 布爾表達式有三種類型: 1.數字布爾型 2.字符布爾型 3.日期布爾型PL/SQL 支持的流程控制結構:
條件控制 1.IF 語句 2.CASE 語句 循環控制 1.LOOP 循環 2.WHILE 循環 3.FOR 循環 順序控制 1.GOTO 語句 2.NULL 語句DECLARE
icode VARCHAR2(4);
irate NUMBER;
BEGIN
icode := 'i203';
SELECT itemrate INTO irate FROM itemfile
WHERE itemcode = icode;
IF irate > 200 THEN --條件判斷
UPDATE itemfile SET itemrate = itemrate - 200
WHERE itemcode = icode;
ELSE
UPDATE itemfile SET itemrate = itemrate - 50
WHERE itemcode = icode;
END IF; --結束
DBMS_OUTPUT.PUT_LINE('itemrate='|| irate);
END;
CASE 語句用於根據單個變量或表達式與多個值進行比較,執行 CASE 語句前,先計算選擇器的值。
BEGIN
CASE ‘&grade’
WHEN ’A’ THEN DBMS_OUTPUT.PUT_LINE(’優異’);
WHEN ’B’ THEN DBMS_OUTPUT.PUT_LINE (優秀’);
WHEN ’C’ THEN DBMS_OUTPUT.PUT_LINE (’良好’);
WHEN ’D’ THEN DBMS_OUTPUT.PUT_LINE (’一般’);
WHEN ’F’ THEN DBMS_OUTPUT.PUT_LINE (’較差’);
ELSE DBMS_OUTPUT.PUT_LINE (’沒有此成績’);
END CASE;
END;
LOOP sequence_of_statements END LOOP;2.WHILE - 根據條件循環
WHILE condition LOOP sequence_of_statements END LOOP;3.FOR - 循環固定的次數
FOR counter IN [REVERSE] value1..value2 LOOP sequence_of_statements END LOOP;loop...exit...when...end loop循環控制
采用loop...exit...when...end loop循環控制的語法結構如下所示:
loop 循環體; exit when循環條件; end loopwhile...loop...end loop循環控制
這種循環控制的語法如下:
while 條件 loop 執行語句段; end loop;
循環例子:
--while循環
--循環輸出Hello world
declare
var_i int := 10;
begin
loop
dbms_output.put_line('Hello world');
if var_i = 0 then
exit;
end if;
var_i := var_i - 1;
end loop;
end;
--loop輸出1-10
declare
var_i int := 1;
begin
loop
dbms_output.put_line('i = ' || var_i);
exit when var_i = 10;
var_i := var_i + 1;
end loop;
End
--while循環1-5
Declare
var_i int:=1;
Begin
while var_i<=10 loop
Dbms_output.put_line('I='||var_i);
Var_i:=var_i+1;
End loop;
End;
--for 循環 : for 變量 in 范圍 loop
--1-10輸出
begin
for i in 1..10 loop
dbms_output.put_line('i = ' || i);
end loop;
end
--對員工的工資判斷,如果少於2000則加50,直到工資滿足為止!
declare
var_sal int;
begin
loop
select sal into var_sal from emp where empno = 7499;
exit when var_sal >= 2000;
update emp set sal = sal + 50 where empno = 7499;
dbms_output.put_line('加50');
end loop;
end;
DECLARE
qtyhand itemfile.qty_hand%type;
relevel itemfile.re_level%type;
BEGIN
SELECT qty_hand,re_level INTO qtyhand,relevel
FROM itemfile WHERE itemcode = 'i201';
IF qtyhand < relevel THEN
GOTO updation; --跳轉到<<updation>>語句塊
ELSE
GOTO quit; --跳轉到<<quit>>
END IF;
<<updation>>
UPDATE itemfile SET qty_hand = qty_hand + re_level
WHERE itemcode = 'i201';
<<quit>>
NULL;
END;
EXECUTE IMMEDIATE dynamic_sql_string
[INTO define_variable_list]
[USING bind_argument_list];
例:
DECLARE
sql_stmt VARCHAR2(200);
emp_id NUMBER(4) := 7566;
emp_rec emp%ROWTYPE;
BEGIN
EXECUTE IMMEDIATE
'CREATE TABLE bonus1 (id NUMBER, amt NUMBER)';
sql_stmt := 'SELECT * FROM emp WHERE empno = :id';
EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING emp_id;
END;
--顯示員工編號為7499的所有信息
declare
Var_row emp%rowtype;
begin
select * into var_row from emp where empno = 7499;
dbms_output.put_line('編號=' || var_row.empno || '姓名=' || var_row.ename);
end;
--動態執行
declare
var_row emp%rowtype;
var_sql varchar(100);
var_empno int;
begin
var_sql := 'select * from emp where empno = :num' ;
execute immediate var_sql into var_row using var_empno;
dbms_output.put_line('編號=' || var_row.empno || '姓名=' || var_row.ename);
end;
--用動態SQL來實現分頁
begin
execute immediate 'select * from (select rownum rn, d.* from (select * from :tableName order by sal desc) d) where rn > :min and rn <= :max' using 'emp' , 1, 5;
End;
access_into_null --在未初化對象時出現 case_not_found --在CASE語句中的選項與用戶輸入的數據不匹配時出現 collection_is_null --在給尚未初始化的表或數組賦值時出現 cursor_already_open --在用戶試圖打開已經打開的游標時出現 dup_val_on_index --在用戶試圖將重復的值存在使用唯一索引的數據庫列中時出現 invalid_cursor --在執行非法游標運算(如打開一個尚未打開的游標)時出現 invalid_number --在將字符串轉換為數字時出現 login_denied --在輸入的用戶名或密碼無效時出現 no_data_found --在表中不存在的請求的行時出現,此外,當程序引用已經刪除的元素時 storage_error --在內存損壞或PL/SQL耗盡內存時出現 too_many_rows --在執行SELECT INTO語句後返回多行時出現 value_error --在產生大小限制錯誤時出現 zero_divide --以零作除數時出現 Others --針對所有異常
處理用戶定義異常
DECLARE
invalidCATEGORY EXCEPTION;
category VARCHAR2(10);
BEGIN
category := '&Category';
IF category NOT IN ('附件','頂蓋','備件') THEN
RAISE invalidCATEGORY;
ELSE
DBMS_OUTPUT.PUT_LINE('您輸入的類別是'|| category);
END IF;
EXCEPTION
WHEN invalidCATEGORY THEN
DBMS_OUTPUT.PUT_LINE('無法識別該類別');
END;
引發應用程序錯誤
DECLARE
rate itemfile.itemrate%TYPE;
rate_exception EXCEPTION; --定義異常
BEGIN
SELECT NVL(itemrate,0) INTO rate FROM itemfile
WHERE itemcode = 'i207';
IF rate = 0 THEN
RAISE rate_exception; --引發異常
ELSE
DBMS_OUTPUT.PUT_LINE('項費率為:' || rate);
END IF;
EXCEPTION
WHEN rate_exception THEN --撲捉異常
RAISE_APPLICATION_ERROR(-20001, '未指定項費率');
END;
引發系統級錯誤
begin
if 10 > 5 then
raise_application_error(-20001, '這個是自定義錯誤顯示');
end if;
end;