1. 程式人生 > >動態SQL和動態PL/SQL

動態SQL和動態PL/SQL

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的一些其他好處所抵消。

16.7 Oracle11g新特性

16.7.1 DBMS_SQL.TO_REFCURSOR函式

16.7.2 DBMS_SQL.TO_CURSOR