将光标用于多个搜索条件

时间:2017-07-19 21:23:43

标签: sql db2 ibm-midrange rpgle

首先,我想为我糟糕的英语道歉,我可能会错过一些关键信息给你们。

反正。我正在开发一个带有子文件的显示文件来显示一些记录。当显示一个选择时,它就像一个魅力,但现在我想为用户开发一个搜索功能。因此,当用户输入不同的搜索条件时,选择将改变,并且光标必须以新的选择以某种方式更新。我正在撕开我的头发,我真的无法让它发挥作用。

我发现了一个来自“mcpressonine”-forum的帖子,有一个人和我一样得到了完全相同的问题,他确实以某种方式解决了这个问题,但我真的不明白他做了什么 - 除了将声明光标放在子程序中我也做了 - 没有成功。

这是他论坛帖子的链接: His post

如果有人解释他做了什么,我会非常感激。也许这家伙的解决方案不再有效,因为他的职位现在已经10岁了。 告诉我,如果信息不够,我会在整个过程中纠正。

谢谢! 亲切的问候,Jesper

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

您只能在嵌入式SQL程序或存储过程中声明一次游标。您还可以声明多个游标。但链接到该游标的SQL语句可能会随时间而变化。

推荐帖子中的建议仍然有效。您可以将游标声明一次(例如在存储过程中),但只要光标首次关闭(如果它已打开)并且只要新的SQL-,游标引用的语句就会随时间而变化。语句已成功准备,然后光标重新打开等。