動態SQL和動態PL/SQL
阿新 • • 發佈:2019-02-18
16.1 NDS語句
16.1.1 EXECUTE IMMEDIATE語句
EXECUTE IMMEDIATE SQL_string [INTO {define_variable[, define_variable]...| record}][USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]...];
我們可以把這個語句用於除了多行查詢以外的任何SQL語句或者PL/SQL塊。如果SQL_string後面帶了分號,這就會按照一個PL/SQL塊來處理;否則,就會按照DML或者DDL語句來處理。
16.1.2 OPEN FOR語句
OPEN {cursor_variable |:host_cursor_variable} FOR SQL_string
[USING bind_argument [, bind_argument]...];
16.2 繫結變數
16.2.2 重複的佔位符
- 當我們執行一個動態SQL字串,我們必須為每一個佔位符都提供一個引數,即使這些佔位符是重複的。
- 如果我們執行的是一個動態PL/SQL塊,我們必須為每一個唯一佔位符提供一個引數。
16.2.3 NULL值的傳遞
我們不能直接將NULL直接量當做引數來進行傳遞。
- 把NULL值隱藏在一個變數後面,如果用一個未初始化的的變數做起來會更容易些。* 通過轉換函式把NULL值顯式的轉換成一個有型別的值。
16.4 動態PL/SQL
- 動態字串必須是在一個有效的PL/SQL塊,這個塊必須是以DECLARE或者BEGIN關鍵字開始,用END關鍵字和分號結束。如果字串不是用分號結尾的,是不會被識別成PL/SQl塊的。
- 動態塊中,我們只能訪問屬於全域性作用範圍的PL/SQl程式碼元素。
- 在動態PL/SQL塊招聘的錯誤可以在執行EXECUTE IMMEDIATE語句的區域性塊中捕獲並處理。
16.5 NDS的建議
16.5.1 對於共享程式使用呼叫者許可權
建議對所有的動態SQL程式都和要加上AUTHID CURRENT_USER子句,尤其對那些計劃要提供給開發人員使用的程式更是如此。
16.5.2 預估並處理動態的錯誤
- 在呼叫EXECUTE IMMEDIATE和OPEN FOR時,總是帶上一個異常處理單元。
- 在每一個異常處理控制代碼裡,記錄下或者顯示錯誤發生時的錯誤訊息以及SQL語句。
- 也可以考慮在這些語句之前加上一個跟蹤機制,這樣我們就可以很容易的對動態SQL的構造和執行進行觀察了。
16.5.3 使用繫結而不是拼接
- 繫結通常更快速
- 繫結的編寫和維護都很容易
- 繫結有助於避免隱式轉換
- 繫結避免了發生程式碼注入的可能性
不過,使用繫結也有一些潛在的缺陷。繫結變數會忽略柱狀統計資訊,因為繫結變數的值是在語句解析後賦值的。對於CBO來說,可用資訊太少了,有可能無法為我們的SQL語句提供最好的執行計劃。
16.5.5 把程式碼注入的風險最小化
- 限制使用者許可權
- 儘可能使用繫結變數
- 檢查動態文字中的危險文字
- 用DBMS_ASSERT校驗輸入
16.6 使用時候使用DBMS_SQL
16.6.1 解析非常長的字串
Oracle10g的EXECUTE IMMEDIATE所能執行的VARCHAR2字串,其內容最大長度限制是32K。如果超過這個長度就要用DBM_SQL了。 不過11g中EXECUTE IMMEDIATE可以執行一個VARCHAR2字串或者一個CLOB,後者的最大長度可以有4GB。
16.6.2 得到查詢的列的資訊
DBMS_SQL允許我們對動態遊標中的列進行描述,以記錄的關聯陣列形式返回每個列的資訊。
16.6.4 把動態遊標的解析最小化
EXECUTE IMMEDIATE有一個缺陷,每次執行一個動態字串時,都需要重新準備,通常包括會解析、優化以及生成執行計劃。對於大部分動態SQL的需求而言,這些步驟所帶來的開銷可以被NDS的一些其他好處所抵消。