·數據中斷的威脅—可能會導致數據丟失;
·使系統難以使用—如可能會減少重用性或者使系統難以維護;
·降低性能—通常是浪費存儲和CPU;
·安全威脅;
詳細內容如下:
1.直接在條件中使用non-deterministic函數:降低性能
non-deterministic函數不依賴于where子句使用的當前行值,可能依賴于上下文從不同的表推進數據,或在數據上執行操作,這些函數并不包含在select列表中。
函數會執行過多的次數,可能對于每個查詢只需要執行一次即可,但是Oracle可能為結果集的每一行都執行了一次,甚至數據源的每一行執行了一次;
·如果不依賴于任何行值,將其放在select function() from dual中;
·如果函數依賴于引用的數據,則將其移到子查詢中,然后連接子查詢和主查詢;
·如果對于相同的值返回相同的結果,則將函數標記為deterministic;
·使用Oracle 11g的結果集緩存功能;
2.捕獲異常處理塊使用WHEN OTHERS THEN:數據中斷的威脅;
通常用來忽略所有不影響事務的錯誤(如唯一索引不能包含重復數據,插入錯誤應該被log);
when others將會防止其他不可預計錯誤傳播,如一個觸發器導致的突發表錯誤可能被隱藏,而造成事務實際上沒有完成它應該做的而在數據庫中事實上已經完成了。
·對于檢查特定的錯誤不要使用when others,如no_data_found。
·不要假設你已經考慮到了任何問題,存儲問題,突發表問題應該反饋給客戶端,而不是僅僅的拋棄;
3.客戶端以對象屬主訪問:安全威脅;
4.客戶端訪問表:安全威脅;
為不同的應用程序建立視圖,避免直接訪問表。
5.將復雜的PL/SQL嵌入PL/SQL:使系統難以使用;
--大塊的SQL代碼,通常是一個復雜的SELECT語句,使用內置函數/過程;
--在內置PL/SQL過程/函數中使用優化器提示;
將復雜的SQL代碼從PL/SQL中提取出來,放到一個視圖中,然后在過程中從視圖上選擇,將優化器提示從過程上移到視圖上。
6.使用數字處理錯誤:使系統難以使用
在PL/SQL中使用RAISE_application_ERROR,而沒有為錯誤碼聲明PL/SQL異常;
·在pl/sql包頭中,聲明異常碼和異常,使用這些異常而不是應用程序錯誤號;
·發送異常時順便帶上一條消息,使用RAISE_APPLICATION_ERROR和恰當的異常碼;
·為單獨的過程創建一個包,該包專門用來聲明異常;
7.使用輸出參數處理錯誤:數據中斷的威脅;
過程和函數生命返回碼作為輸出參數,通知調用者問題;
建議使用聲明的異常處理錯誤,異常必須由調用者處理,而不會被不可預料的忽略,并且可以同時聲明錯誤碼和消息,不需要OUTPUT參數;
8.在視圖中格式化數據:使系統難以使用;
--在視圖的DATE和NUMBER列上使用to_char函數;
--在視圖中結合字符串;
在終端進行數據格式化,而不是數據庫中,視圖不應該進行任何的格式化;
9.硬編碼本地Varchar2變量尺寸:使系統難以使用;
-- PL/SQL函數/過程中聲明本地Varchar2類型存儲表的值,硬編碼長度;
--視圖以硬編碼格式聲明Varchar2長度;
使用%type引用基層表對象。
10.忽略異常:數據中斷的威脅;
-- "Exception When others then NULL;"
可能會導致如空間錯誤之類的嚴重錯誤被忽略。
·如果不希望任何錯誤影響事務,則使用自治事務,并將錯誤log到錯誤表中;
·如果要處理某些具體的錯誤,則使用特定的exception;
11.不使用綁定變量更改參數:降低可用性;
經常使用相同的語句執行,不使用綁定變量,而使用文本值;
會導致每次都編譯查詢;
12.在觸發器中依賴于條件列值,數據中斷的威脅;
if updating('ColumnName') then;
在大多數GUI情況下,該方法不能正確的工作,因為GUI層保留所有字段,而不是單獨的字段,如下:
create table tbl(col1 number, col2 varchar2(10));
CREATE OR REPLACE TRIGGER trig1
BEFORE UPDATE ON tbl
FOR EACH ROW
BEGIN
if not updating('col1') then
raise_application_error (-20001,'Col1 was not updated');
end if;
END;
/
insert into tbl values (1,'test');
update tbl set col1=1;
比較:new.column和:old.column,如果列為NULL,確保使用了DECODE。
13.依賴于在包變量中的上下文信息:數據中斷的威脅;
依賴對象結構更改會導致全部變量的清空。
·使用sys_context存儲簡單的交叉調用上下文;
·使用臨時表存儲復雜的內部事務上下文;
·使用表存儲復雜的內部調用上下文;
14.依賴于外部上下文初始化:數據中斷的威脅;
視圖和過程依賴于sys_context()得到上下文信息,上下文通常要求調用者調用存儲過程設置。
數據庫和應用程序之間的網絡會斷,大多數現代網絡都會自動重新連接,但是初始化過程不會調用并且舊的上下文將會丟失。
·使用登陸觸發器設置上下文;
15.分布式觸發器的二次處理:數據中斷的威脅;
傳播數據更新遠程系統;
在第二個子系統中使用LOG表,在觸發器中使用When others LOG任何異常,使用dbms_utility.format_error_stack或sqlerrm捕獲詳細信息;
16.存儲rowid在之后引用,數據中斷的威脅;
ROWID值存儲在表或客戶端,以在之后引用;
ROWID會更改,使用主鍵引用;
17.存儲空的LOBs,降低性能;
在CLOB字段存儲Empty CLOB而不是NULL;
Oracle為EMPTY CLOBs分配空間;
18.太多層次的視圖:降低性能;
優化器可能會放棄使用索引。
只要可能考慮使用連接代替子查詢;
使用物化視圖或者維護一個聚集表;
19.非自治事務中的事務控制,數據中斷的威脅;
在無PRAGMA AUTONOMOUS TRANSACTION的事務中commit和rollback。
20.觸發器依賴于執行的順序
觸發器依賴于其他觸發器,如log/audit由其他觸發器完成;
打包相互依賴的商業邏輯到存儲過程中,在然后在觸發器中調用過程;
將內部相互依賴的過程組合成一個觸發器;
確保語句級觸發器在行級觸發器后執行。
21.使用Sequence nextval而沒有curval:數據中斷的威脅;
不要使用currval作為上下文讀取,顯示傳遞ID或使用sys_context;
序列是批分配的,currval+1不一定等于nextval。
22.使用序列作為計數器,數據中斷的威脅;
23.在常量上使用綁定變量:降低性能;
24.對存在的檢查使用計算列(聚集):降低性能
在內查詢中計算聚集,然后在外查詢再將計算的值與某些值比較,這會導致聚集值被拋棄;
25.為流程控制使用異常:數據中斷的威脅;
--使用exception when XXX then blocks而不是錯誤處理;
exception中僅處理錯誤。
26.日期列(截去時間)比較,數據中斷的威脅;
27.對不存在的值使用0-1之類的數字:使系統難以使用;
對于一些判斷情況,通常使用0,1,-1之類的表示,很難理解;
使用null表示不存在,未知。
28.對于連續的作業不使用專用包:使系統難以使用;
作業的內容是使包體中的一個過程,函數;
29.將任何東西都打包到存儲過程中,Ref Cursor用來讀數據,使系統難以使用;
新聞熱點
疑難解答