最近項目在做版本升級,涉及到原有功能的表結構修改,需要將舊數據轉移到新庫中,項目上定的方案是在舊數據庫中通過存儲過程生成新數據庫的INSERT
語句。故對此塊內容做了複習整理。
通過一個簡單的例子分析PL/SQL程序塊結構
- 聲明部分
- 用於聲明變量、常量、遊標(cursor)、記錄類型(record type)
- 執行部分
- 用於執行各種對數據庫操作的語句和對異常進行處理的邏輯
--格式:變量名 數據類型;
v_name VARCHAR2(128);
--格式: 變量名 CONSTRANT 數據類型 := value;
v_days_in_year CONSTRANT INTEGER := 365;
執行部分邏輯是按從上到下的順序執行的,PL/SQL 支持條件選擇語句、循環語句
IF 語句最簡形式
IF condition THEN
DBMS_OUTPUT.PUT_LINE('當condition爲TRUE時,執行');
END IF;
IF 語句擴展形式
IF condition1 THEN
DBMS_OUTPUT.PUT_LINE('當condition1爲TRUE時,執行');
ELSIF condition2 THEN
DBMS_OUTPUT.PUT_LINE('當condition2爲TRUE時,執行');
ELSE
DBMS_OUTPUT.PUT_LINE('當condition1爲FALSE且condition2爲FALSE時,執行');
END IF;
一個IF
語句最多隻能有一個ELSE
分支,可以有0個
或多個
ELSIF condition THEN
分支
CASE 語句最簡形式
CASE age
WHEN 10 THEN
DBMS_OUTPUT.PUT_LINE('當age值爲10時,執行');
END CASE;
CASE 語句擴展形式
CASE age
WHEN 10 THEN
DBMS_OUTPUT.PUT_LINE('當age值爲10時,執行');
WHEN 20 THEN
DBMS_OUTPUT.PUT_LINE('當age值爲20時,執行');
WHEN 30 THEN
DBMS_OUTPUT.PUT_LINE('當age值爲30時,執行');
ELSE
DBMS_OUTPUT.PUT_LINE('當age值爲其它值時,執行');
END CASE;
一個CASE
語句最多隻能有一個ELSE
分支,可以有一個或多個WHEN THEN
分支
CASE 語句變形
CASE
WHEN age = 10 THEN
DBMS_OUTPUT.PUT_LINE('當age值爲10時,執行');
WHEN age = 20 THEN
DBMS_OUTPUT.PUT_LINE('當age值爲20時,執行');
WHEN age = 30 THEN
DBMS_OUTPUT.PUT_LINE('當age值爲30時,執行');
ELSE
DBMS_OUTPUT.PUT_LINE('當age值爲其它值時,執行');
END CASE;
CASE 語句賦值給變量,THEN
後面的語句不要加;
appraisal :=
CASE
WHEN grade = 'A' THEN '優'
WHEN grade = 'B' THEN '良'
WHEN grade = 'C' THEN '差'
ELSE ''
END CASE;
LOOP
num NUMBER := 0;
total NUMBER := 0;
LOOP
num := num + 1;
total := total + num;
EXIT WHEN num = 10;--當num=10時,退出循環
END LOOP;
DBMS_OUTPUT.PUT_LINE(total);
--退出循環
EXIT WHEN condition;
--退出當前循環進入下一次循環
CONTINUE WHEN condition;
FOR
FOR item IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(item);
END LOOP;
每次迭代的步長都是1,當在IN
關鍵字後面加上REVERSE
關鍵字時,將反轉遍歷的順序,在上例中將變爲從10~1
WHILE
WHILE condition LOOP
DBMS_OUTPUT.PUT_LINE();
condition := FALSE;
END LOOP;
--格式: 變量名 表名.字段名%TYPE;
v_name employee.name%TYPE;
--格式: 變量名 表名%ROWTYPE;
v_row employee%ROWTYPE;
表名.字段名%TYPE : 用於單個字段
表名%ROWTYPE : 用於表中的一行記錄
使用以上兩種方式定義變量的數據類型,使聲明的變量的數據類型將與指定表中指定的字段的數據類型始終保持一致
如果我們需要定義一個變量存儲多個字段(大於一個字段但小於表中的全部字段 或 多個字段來自多個表)的值時,我們可以聲明一個record type
TYPE employeeAddrType IS RECORD(
name VARCHAR2(128),
addr VARCHAR2(256)
);
v_employee_adr employeeAddrType;
遊標
遊標的使用由以下幾步操作構成:
- 聲明遊標
- 打開遊標
- 邏輯處理
- 關閉遊標
DECLARE
--聲明遊標
CURSOR my_cursor IS SELECT * FROM employee;
BEGIN
--打開遊標
OPEN my_cursor;
--邏輯處理
LOOP
EXIT WHEN my_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(my_cursor.name);
END LOOP;
--關閉遊標
CLOSE my_cursor;
END;
將遊標中的數據賦值到指定的變量中
FETCH my_cursor INTO v_row;
使用遊標更新數據時,在聲明遊標的結尾需要使用FOR UPDATE
,例如:
CURSOR my_cursor IS SELECT * FROM employee FOR UPDATE;
在邏輯處理部分的UPDATE
語句中使用WHERE CURRENT OF 遊標名
指定更新當前行
UPDATE employee SET name = name||'TEST' WHERE CURRENT OF my_cursor;
如何傳參到遊標中呢?
在遊標聲明處指定參數,例如:
CURSOR my_cursor(v_id employee.id%TYPE) IS SELECT * FROM employee WHERE id=v_id;
聲明瞭變量後如何使用呢,在打開遊標處設置參數值
OPEN my_cursor(1);
過程
CREATE OR REPLACE PROCEDURE procedure_name
IS
--聲明變量
BEGIN
--邏輯處理
END procedure_name;
上面的存儲過程是無參的,而實際工作中我們可能會遇到需要傳參或返回值的情況
參數有三種模式,分爲:
- 輸入參數: in
- 輸出參數: out
- 輸入輸出參數: in out
默認模式爲: in
CREATE OR REPLACE PROCEDURE procedure_name(
business_type in varchar2(4),
apply_code in varchar2(32),
business_stauts out varchar2(4)
) IS
--聲明變量
v_business_status varchar2(4);
v_sql varchar2(200);
BEGIN
--邏輯處理
v_sql := 'SELECT business_status INTO v_business_status FROM dp_c_business_apply where business_type = '''||business_type||''' and apply_code = '''||apply_code||'';'
execute immediate v_sql;
business_status := v_business_status;
END procedure_name;
調用存儲過程
DECLARE
v_status varchar2(200);
BEGIN
EXECUTE procedure_name('BS01','201907200000001',v_status);
END;
在上面的例子中我們是按各參數的位置進行傳值的,我們還可以按參數名稱進行傳值
v_status varchar2(200);
BEGIN
EXECUTE procedure_name(business_type=>'BS01',apply_code=>'201907200000001',business_status=>business_status);
END;