1. 程式人生 > >動態SQL中使用Open for語句

動態SQL中使用Open for語句

Open for本是為了支援遊標變數,現在用它實現多行動態查詢。OPEN FOR的語法如下:

OPEN{cursor_variable | :host_cursor_viable}FOR SQL_string

                [USING bind_argument [, bind_argument]…];

解釋:

Cursor_variable是一種弱型別的遊標變數。

:host_cursor_variable是在PL/SQL宿主環境下宣告的遊標變數,如Oracle呼叫介面程式。

SQL_string包含動態執行的SELECT語句。

USING子句與EXECUTE IMMEDIATE語句遵循相同的規則。

使用OPEN FOR語句開啟動態查詢的例子:

PROCEDURE show_parts_inventory(

 parts_table IN VARCHAR2, where_in IN VARCHAR2)

IS

 TYPE query_curtype IS REF CURSOR;

 dyncur query_curtype; 

BEGIN

 OPEN dyncur FOR

      'SELECT * FROM' || parts_table || 'WHERE' || where_in;

                。。。

執行OPEN FOR語句時,PL/SQL執行引擎操作如下:

1、  將遊標變數與在查詢字串找到的查詢相關聯。

2、  對繫結引數求值,並用這些值替換查詢字串內的佔位符。

3、  執行查詢。

4、  識別結果集。

5、  將遊標放在結果集第一行。

6、  把由%ROWCOUNT返回的行計數值歸零。

注意,查詢中任何繫結引數(由USING子句提供),僅當遊標變數開啟時才能求值。這意味著如果我們想對相同的動態查詢使用不同的繫結引數值,

就必須使用該引數再執行一次OPEN FOR語句。

執行多行查詢需遵循以下步驟:

1、  宣告一個REFCURSOR型別(或使用Oracle定義的SYS_REFCURSOR弱CURSOR型別)。

2、  基於這個REF CURSOR型別宣告一個遊標變數。

3、  用這個遊標變數開啟查詢字串。

4、  使用FETCH語句提供查詢確認的一行或多行結果集。

5、  必要時檢查遊標屬性(%FOUND、%NOTFOUND、%ROWCOUNT、%ISOPEN)。

6、  使用標準CLOSE語句關閉遊標變數。

/*顯示任何一個表中由WHERE子句所選出的行的指定列的內容(對數字、日期和字串列有效)*/

/*引數說明:tab:表名、col:列名、whr:條件*/

PROCEDURE showcol(tab IN VARCHAR2,

                  col IN Varchar2,

                  whr IN VARCHAR2:=NULL)

IS

         cv SYS_REFCURSOR;

         val VARCHAR2(32767);

BEGIN

 OPEN cv FOR

--注意字串之間的空格

      'SELECT ' || col ||

      ' FROM ' || tab ||

      ' WHERE ' || NVL(whr, '1 = 1');

 LOOP

   --取cv的值給val,如果找不到就退出,和顯示遊標相同

   FETCH cv INTO val;

   EXIT WHEN cv%NOTFOUND;

   --如果取到第一行,顯示頭部的資訊

    IFcv%ROWCOUNT = 1

     THEN

       Dbms_Output.put_line(RPAD('_',60,'_'));

       Dbms_Output.put_line(

                   'Contents of ' || UPPER(tab)|| '.' || UPPER(col));

       Dbms_Output.put_line(RPAD('_',60,'_'));

     END IF;

     Dbms_Output.put_line(val);

  END LOOP;

   --記得關閉遊標

  CLOSE cv;

END;

/*升級版showcol程式,顯示帶有一個時間列,並且時間列在一定範圍數值內的所有列的資訊*/

PROCEDURE showcol(tab VARCHAR2,

                      col VARCHAR2,

                      dtcol VARCHAR2,

                      dt1 DATE,

                      dt2 DATE := NULL)

IS

   cvSYS_REFCURSOR;

  val VARCHAR2(32767);

BEGIN

 OPEN cv FOR

  --注意空格

      'SELECT ' || col ||

      ' FROM ' || tab ||

      ' WHERE ' || dtcol ||

      ' BETWEEN TRUNC (:startdt) AND TRUNC (:enddt)'

    USING dt1, NVL (dt2, dt1+1);

 LOOP

   --取cv的值給val,如果找不到就退出

   FETCH cv INTO val;

   EXIT WHEN cv%NOTFOUND;

   --如果取到第一行,顯示資訊

   IF cv%ROWCOUNT = 1

     THEN

       Dbms_Output.put_line(

                   'Contents of ' || UPPER(tab)|| '.' || UPPER(col) ||

                   ' for ' || UPPER(dtcol) ||

                   ' between ' || dt1 || ' AND' || NVL (dt2, dt1+1));

    END IF;

   Dbms_Output.put_line(val);

  ENDLOOP;

 CLOSE cv;

END;