Oracle動態SQL語句的簡單執行

來源:互聯網
上載者:User

在使用ODP.NET進行Oracle編程時,有時候SQL語句非常複雜,需要採用動態構造查詢語句的情況,有兩種方法可以構造動態SQL語句,並執行返回結果集。

1、在資料訪問層構造SQL語句

例如下面的語句,將構造完整的SQL語句賦值給CommandText,再傳遞到資料庫進行執行,返回結果集。

loadCommand.CommandType = CommandType.Text
   loadCommand.CommandText = "Select * From Users"

   dataAdapter .SelectCommand = loadCommand
   dataAdapter . Fill(data)

   dataAdapter .SelectCommand = loadCommand
   dataAdapter . Fill(data)

該方法需要將整個SQL的構造過程放在DataAccess層,商務邏輯發生變化,修改不方便,而且每次查詢需要傳遞給資料庫很長的查詢字串,傳遞參數的效率也不高。

2、在預存程序中構造動態SQL語句並執行

 以下為一個完整的案例(經過刪減),其中RefCursor 為自訂遊標類型

PROCEDURE G_Search(P_YearNO      IN NUMBER,
                              P_ControlType IN NUMBER,
                              P_Progress    IN CHAR,
                              P_DepartID    IN VARCHAR2,
                              P_ProjectName IN NVARCHAR2,
                              C_Projects    OUT RefCursor) IS
        e_ErrInterruption EXCEPTION;
        v_ErrID       NUMBER; --Variable to hold the errorlog id
        v_ErrCode     NUMBER; --Variable to hold the error message code
        v_ErrText     VARCHAR2(512); --Variable to hold the error message text
        v_ErrProc     VARCHAR2(50) := 'G_Search';
        v_DepartID    VARCHAR2(16);
        v_ProjectName NVARCHAR2(128);
        v_SQL         VARCHAR2(512);
        v_Where       VARCHAR2(256);
    BEGIN
    
        v_SQL   := 'SELECT PROJECTID, PARENTID, PROJECTNAME ';
        v_SQL   := v_SQL || ' FROM PROJECTS A';
        v_Where := ' Where';
    
        -- 年度
        IF P_YearNO < 9999 THEN
            v_Where := v_Where || '  A.YearNO = ' || P_YearNO || ' And';
        ELSE
            v_Where := v_Where || '  A.YearNO < ' || P_YearNO || ' And';
        END IF;
        -- 控制類別
        IF P_ControlType = 9 THEN
            v_Where := v_Where || ' A.ControlType < 9 And';
        ELSE
            v_Where := v_Where || ' A.ControlType = ' || P_ControlType ||
                       ' And';
        END IF;
        -- 進度
        IF P_Progress < 'Z' THEN
            v_Where := v_Where || ' A.Progress = ''' || P_Progress || ''' And';
        ELSE
            v_Where := v_Where || ' A.Progress < ''' || P_Progress || ''' And';
        END IF;
    
        IF TRIM(P_DepartID) <> '%' THEN
            v_Where := v_Where || ' A.DepartID = ''' || P_DepartID || ''' And';
        ELSE
            v_Where := v_Where || ' A.DepartID Like ''' || P_DepartID ||
                       ''' And';
        END IF;
        --項目名稱
        v_ProjectName := NVL(P_ProjectName,
                             '%');
        IF v_ProjectName <> '%' THEN
            v_ProjectName := '%' || P_ProjectName || '%';
        END IF;
        v_Where := v_Where || ' A.ProjectName Like ' || '''' || v_ProjectName ||
                   ''' And';
              
        v_SQL := v_SQL || v_Where;
    
        OPEN C_PROJECTS FOR v_SQL;
    
        --COMMIT;
    EXCEPTION
        --根據需要定義錯誤異常
        WHEN OTHERS THEN
            --ROLLBACK;
            v_ErrID   := SQLCODE;
            v_ErrText := SQLERRM;
            raise_application_error(v_ErrID,
                                    v_ErrText);
    END G_Search;

該方法只需要傳遞給預存程序一些參數,使用遊標返回資料。參數傳遞效率較高,而且商務邏輯在預存程序中,調整比較方便。該方法關鍵的在下面的語句:
Open C_Projects For v_SQL;
它直接使用遊標開啟構造的查詢字串即可。

注意事項:

A)、構造的SQL語句最後不能帶有分號;
B)、SQL語句中對於字元和字串的條件需要用單引號包括起來
C)、最重要:動態SQL語句需要防止SQL注入攻擊。我們採用最簡單的辦法,只允許一個關鍵詞查詢,將關鍵詞中的所有空格去掉。對於多關鍵詞,需要將他們用空格拆開,再構造。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.