需要記住的是DECLARE
聲明是而不是可執行文件。這是一個編譯時聲明。 PREPARE
和OPEN
是可執行的。
下面是一個使用動態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;
顯示您的代碼或至少一些您想要做的事例。你希望聲明在運行之間改變?你得到什麼錯誤信息? – Charles
這篇文章剛剛建立了一個sql語句。然後運行它。我可以看到按順序排列的順序正在改變。 – danny117