回顧內容:
- 怎麼創建表空間?
- 怎麼創建用戶?怎麼給用戶權限?
本次學習內容講解:
- PL/SQL
1)、PL/SQL塊的結構。
2)、一般運算符、邏輯運算符。
3)、常量和變量的聲明。
4)、標識符命名規則。
5)、註釋。
- PL/SQL數據類型
- 標量數據類型。
- LOB數據類型。
- 屬性類型:%TYPE、%ROWTYPE。
- PL/SQL控制語句
1)、條件控制語句:IF、CASE。
2)、循環控制語句:LOOP、WHILE、FOR。
3)、順序控制語句:NULL。
- 異常
1)、預定義異常。
2)、自定義異常。
- 遊標
1)、靜態遊標(顯示和隱式)。
1、循環遊標:LOOP、FOR。
2、顯式遊標屬性:%FOUND、%NOTFOUND、%ROWCOUNT、%ISOPEN。
3、使用顯示遊標刪除或更新。
4、NO_DATA_FOUND和%NOTFOUND區別。
2)、動態遊標。
- 存儲過程
1)、子程序組成:聲明部分、可執行部分、異常處理部分。
2)、創建存儲過程、調用存儲過程(按位置、按名稱)。
3)、程序過程的參數模式:IN、OUT、IN OUT。
4)、存儲過程的訪問權限。
5)、刪除存儲過程。
6)、存儲過程調試。
7)、存儲過程規範。
一、for讀取遊標
-- Created on 2014/7/24 by ADMINISTRATOR
declare
-- Local variables here
CURSOR cursor_emp IS SELECT ename,sal FROM scott.emp ;
begin
-- Test statements here
--使用for循環
FOR emp_row IN cursor_emp LOOP
dbms_output.put_line(emp_row.ename || emp_row.sal || ' ' || cursor_emp%Rowcount);
END LOOP;
end;
二、loop讀取遊標
declare
-- Local variables here
i integer;
v_ename scott.emp.ename%TYPE;
v_sal scott.emp.sal%TYPE;
CURSOR cursor_emp IS SELECT ename,sal FROM scott.emp;
begin
-- Test statements here
--打開遊標 如果沒有打開纔打開
IF NOT cursor_emp%ISOPEN THEN
OPEN cursor_emp;
END IF;
--使用loop讀取遊標
LOOP
--讀取下一行
FETCH cursor_emp INTO v_ename,v_sal;
dbms_output.put_line(v_ename || v_sal);
--如果沒有行 則退出
EXIT WHEN cursor_emp%NOTFOUND;
END LOOP;
--關閉遊標
CLOSE cursor_emp;
end;
三、刪除表的存儲過程:
/**
*刪除數據庫表
in_tablename 刪除表的名稱
out_err_code 0刪除成功 -1沒有找到相關的表 -2 存儲過程執行異常
out_err_msg 返回的執行信息
*/
create or replace procedure p_del_table(
in_tablename IN VARCHAR2,
out_err_code OUT VARCHAR2,
out_err_msg OUT VARCHAR2
)
AS
v_count NUMBER;
begin
SELECT COUNT(1) INTO v_count FROM dual WHERE EXISTS (
SELECT * FROM User_Tables WHERE table_name=upper(in_tablename)
);
IF v_count > 0 THEN
out_err_code := 0;
out_err_msg := '刪除成功';
EXECUTE IMMEDIATE 'DROP TABLE ' || in_tablename;
ELSE
out_err_code := -1;
out_err_msg := '沒有找到表';
DBMS_OUTPUT.put_line('沒有找到表');
END IF;
EXCEPTION
WHEN OTHERS THEN
out_err_code := -2;
out_err_msg := '存儲過程執行異常';
end p_del_table;
/
l四、異常:
/*
===========================================================
| 預定義異常
============================================================
*/
DECLARE
v_ename employee.ename%TYPE;
BEGIN
SELECT ename INTO v_ename
FROM employee
WHERE empno=1234;
dbms_output.put_line('僱員名:'||v_ename);
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('僱員號不正確');
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('查詢只能返回單行');
WHEN OTHERS THEN
dbms_output.put_line('錯誤號:'||SQLCODE||'錯誤描述:'||SQLERRM);
END;
/*
===========================================================
| 預定義異常
============================================================
*/
DECLARE
v_empno scott.EMP.EMPNO%TYPE ;
EMPNO_REPEAT EXCEPTION; --1.定義異常變量
PRAGMA EXCEPTION_INIT(EMPNO_REPEAT,-1407); --2.關聯異常代碼 ,1407不能爲NULL值
BEGIN
UPDATE scott.EMP SET empno = NULL WHERE empno = 7369;
EXCEPTION
WHEN EMPNO_REPEAT THEN --3、捕捉異常定義的異常處理
DBMS_OUTPUT.put_line('部門編號不能爲空');
END;
/*
===========================================================
| 用戶自定義異常
============================================================
*/
DECLARE
v_empno scott.EMP.EMPNO%TYPE := 7000;
NO_RESULT EXCEPTION; --1.定義異常變量
BEGIN
UPDATE scott.EMP SET sal = sal+100 WHERE empno = v_empno;
--2.判斷是否有執行UPDATE
IF SQL%NOTFOUND THEN
RAISE NO_RESULT; --3.沒有執行UPDATE,拋出自定義異常
END IF;
EXCEPTION
WHEN NO_RESULT THEN --4.捕獲異常
DBMS_OUTPUT.PUT_LINE('你的數據更新語句失敗了!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;
/*
===========================================================
| 用戶自定義異常
============================================================
*/
CREATE OR REPLACE FUNCTION F_TEST(i_code IN NUMBER)
RETURN NUMBER IS RET_CODE NUMBER;
BEGIN
IF i_code IS NULL THEN
RAISE_APPLICATION_ERROR(-20991,'i_code不能爲空'); --1.寫入自定義代碼和錯誤信息
ELSIF i_code > 1 THEN
RAISE_APPLICATION_ERROR(-20992,'i_codeD太大了'); --1.寫入自定義代碼和錯誤信息
ELSE
RET_CODE := i_code;
RETURN RET_CODE;
END IF;
END F_TEST;
DECLARE
v_result NUMBER;
v_code NUMBER;
CODE_NOT_NULL EXCEPTION; --定義異常
CODE_LIMITED EXCEPTION; --定義異常
PRAGMA EXCEPTION_INIT(CODE_NOT_NULL,-20991); --2.初始化異常信息
PRAGMA EXCEPTION_INIT(CODE_LIMITED,-20992); --2.初始化異常信息
BEGIN
--v_result := F_TEST(NULL);
v_result := F_TEST(2); --3.調用函數
EXCEPTION --4.捕獲異常
WHEN CODE_NOT_NULL THEN
DBMS_OUTPUT.put_line('代碼不能爲空');
WHEN CODE_LIMITED THEN
DBMS_OUTPUT.put_line('數字太大了哦');
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('其它異常');
END;
預定義異常:
錯誤號 |
異常錯誤信息名稱 |
說明 |
ORA-0001 |
Dup_val_on_index |
違反了唯一性限制 |
ORA-0051 |
Timeout-on-resource |
在等待資源時發生超時 |
ORA-0061 |
Transaction-backed-out |
由於發生死鎖事務被撤消 |
ORA-1001 |
Invalid-CURSOR |
試圖使用一個無效的遊標 |
ORA-1012 |
Not-logged-on |
沒有連接到ORACLE |
ORA-1017 |
Login-denied |
無效的用戶名/口令 |
ORA-1403 |
No_data_found |
SELECT INTO沒有找到數據 |
ORA-1422 |
Too_many_rows |
SELECT INTO 返回多行 |
ORA-1476 |
Zero-divide |
試圖被零除 |
ORA-1722 |
Invalid-NUMBER |
轉換一個數字失敗 |
ORA-6500 |
Storage-error |
內存不夠引發的內部錯誤 |
ORA-6501 |
Program-error |
內部錯誤 |
ORA-6502 |
Value-error |
轉換或截斷錯誤 |
ORA-6504 |
Rowtype-mismatch |
宿主遊標變量與 PL/SQL變量有不兼容行類型 |
ORA-6511 |
CURSOR-already-OPEN |
試圖打開一個已處於打開狀態的遊標 |
ORA-6530 |
Access-INTO-null |
試圖爲null 對象的屬性賦值 |
ORA-6531 |
Collection-is-null |
試圖將Exists 以外的集合( collection)方法應用於一個null pl/sql 表上或varray上 |
ORA-6532 |
Subscript-outside-limit |
對嵌套或varray索引得引用超出聲明範圍以外 |
ORA-6533 |
Subscript-beyond-count |
對嵌套或varray 索引得引用大於集合中元素的個數. |