2017-07-19 47 views
-1

首先,我想爲我的壞英語道歉,並且有可能我錯過了一些關鍵信息給你們。在多個搜索條件下使用光標

反正。我正在開發一個帶有子文件的顯示文件來顯示一些記錄。它顯示一個選擇時的功能就像一個魅力,但現在我想爲用戶開發一個搜索功能。所以當用戶輸入不同的搜索條件時,選擇會改變,並且遊標必須以某種方式更新新的選擇。我正在把我的頭髮脫掉,我真的無法得到這個工作。

我從「mcpressonine」-forum找到了一篇文章,有一個人得到了和我一樣的問題,他做了某種解決方法,但我不明白他做了什麼 - 除了將聲明遊標放入我也做了子程序 - 沒有成功。

這裏是他的論壇帖子的鏈接: His post

如果有人解釋他做了什麼,我會非常感激。也許這個傢伙的解決方案現在已經有10年的歷史了,所以他不再有效。 告訴我,如果信息不夠,我會一路糾正。

謝謝! 親切的問候,Jesper

+0

顯示您的代碼或至少一些您想要做的事例。你希望聲明在運行之間改變?你得到什麼錯誤信息? – Charles

+0

這篇文章剛剛建立了一個sql語句。然後運行它。我可以看到按順序排列的順序正在改變。 – danny117

回答

0

您可以在嵌入式SQL程序或存儲過程中只聲明一次遊標。您也可以聲明多個遊標。但是鏈接到該遊標的SQL語句會隨着時間的推移而變化。

轉介帖子中的建議仍然有效。您可以一次聲明遊標(例如在存儲過程中),但只要該遊標首次關閉(如果它已打開)並且只要新的SQL-聲明已成功準備,然後光標重新打開等。

+0

如果OP實際需要動態SQL,還有待觀察。根據不同的情況,靜態可能會起作用。 – Charles

1

需要記住的是DECLARE聲明是而不是可執行文件。這是一個編譯時聲明。 PREPAREOPEN是可執行的。

下面是一個使用動態SQL的完整工作程序,請注意DeclareCursor子程序從未實際調用過。重要的是在執行PREPARE語句時在gSqlStmt中的聲明。

**FREE 
ctl-opt main(mymain); 
ctl-opt option(*srcstmt); 

dcl-c QUOTE const(''''); 

dcl-s gSqlStmt varchar(500); 

dcl-proc MyMain; 
    dcl-s company char(3); 
    dcl-s part char(25); 
    dcl-s desc char(30); 
    dcl-s msg  char(50); 
    dcl-s selComp char(3); 

    selComp = 'A06'; 
    gSqlStmt = 'select pmco#, pmpart, pmdesc' 
      + ' from pdpmast' 
      + ' where pmco# = ' + QUOTE + selComp + QUOTE; 

    exsr OpenCursor; 
    exsr FetchData; 
    exec SQL close C1; 

    selComp = 'A15'; 
    gSqlStmt = 'select pmco#, pmpart, pmdesc' 
      + ' from pdpmast' 
      + ' where pmco# = ' + QUOTE + selComp + QUOTE; 
    exsr OpenCursor; 
    exsr FetchData; 
    exec SQL close C1; 

    *INLR = *ON; 
    return; 

    begsr DeclareCursor; 
    exec SQL 
     declare C1 cursor for S1; 
    endsr; 

    begsr OpenCursor; 
    exec SQL prepare S1 from :gSqlStmt; 
    exec SQL open C1; 
    endsr; 

    begsr FetchData; 
    exec sql fetch next from C1 into :company, :part, :desc; 
    msg = company + ':' + part + ':' + %subst(desc:1:20); 
    dsply msg; 
    endsr; 
end-proc; 

除了沒有任何錯誤處理,上面包含了直接將輸入變量selComp連接到語句中的錯誤做法。由於SQL注入攻擊,這在任何語言中都不是一個好主意。

使用參數標記的更好的版本如下。請注意,該聲明不需要再改變。所以我只需要準備一次。記錄選擇取決於調用OPEN ... USING...語句時的selComp值。

**FREE 
ctl-opt main(mymain); 
ctl-opt option(*srcstmt); 

dcl-s gSqlStmt varchar(500); 

dcl-proc MyMain; 
    dcl-s company char(3); 
    dcl-s part char(25); 
    dcl-s desc char(30); 
    dcl-s msg  char(50); 
    dcl-s selComp char(3); 

    gSqlStmt = 'select pmco#, pmpart, pmdesc' 
      + ' from pdpmast' 
      + ' where pmco# = ?'; 
    exec SQL prepare S1 from :gSqlStmt; 

    selComp = 'A06'; 
    exsr OpenCursor; 
    exsr FetchData; 
    exec SQL close C1; 

    selComp = 'A15'; 
    exsr OpenCursor; 
    exsr FetchData; 
    exec SQL close C1; 

    *INLR = *ON; 
    return; 

    begsr DeclareCursor; 
    exec SQL 
     declare C1 cursor for S1; 
    endsr; 

    begsr OpenCursor; 
    exec SQL open C1 using :selComp; 
    endsr; 

    begsr FetchData; 
    exec sql fetch next from C1 into :company, :part, :desc; 
    msg = company + ':' + part + ':' + desc; 
    dsply msg; 
    endsr; 
end-proc; 

但是,實際上沒有必要在這裏動態SQL。一個帶有主變量的靜態語句可以正常工作。對於靜態SQL,我不需要PREPARE任何東西,也不需要在OPEN上指定selComp。所有這些都是在編譯時自動完成的。

**FREE 
ctl-opt main(mymain); 
ctl-opt option(*srcstmt); 

dcl-s gSqlStmt varchar(500); 

dcl-proc MyMain; 
    dcl-s company char(3); 
    dcl-s part char(25); 
    dcl-s desc char(30); 
    dcl-s msg  char(50); 
    dcl-s selComp char(3); 

    selComp = 'A06'; 
    exsr OpenCursor; 
    exsr FetchData; 
    exec SQL close C1; 

    selComp = 'A15'; 
    exsr OpenCursor; 
    exsr FetchData; 
    exec SQL close C1; 

    *INLR = *ON; 
    return; 

    begsr DeclareCursor; 
    exec SQL 
     declare C1 cursor for 
      select pmco#, pmpart, pmdesc 
      from pdpmast 
      where pmco# = :selComp; 
    endsr; 

    begsr OpenCursor; 
    exec SQL open C1; 
    endsr; 

    begsr FetchData; 
    exec sql fetch next from C1 into :company, :part, :desc; 
    msg = company + ':' + part + ':' + desc; 
    dsply msg; 
    endsr; 
end-proc;