在db2中准备fetch语句

时间:2017-02-08 18:25:57

标签: sql db2 ibm-midrange db2-400

我一直在尝试在db2中准备一个Fetch语句,如下所示

Stmt = %trim('FETCH EXSQCRS INTO ?'); 
EXEC SQL PREPARE SQLSTMT2 FROM :STMT ;

EXSQCRS是一个游标。

但这是失败的-104错误。关于如何写这个的任何线索?

2 个答案:

答案 0 :(得分:2)

FETCH不是可以准备的陈述。它只是一个可执行语句。见Actions allowed on SQL statements

您需要阅读Embedded SQL programming

动态SQL的简单示例

 D EMPNUM          S              6A 
 D NAME            S             15A
 D STMT            S            500A   INZ('SELECT LASTNAME         -
 D                                     FROM CORPDATA.EMPLOYEE WHERE -
 D                                     EMPNO = ?')

  //************************************************************
  // Prepare STMT as initialized in declare section            *
  //************************************************************
  /FREE
   EXEC SQL
    PREPARE S1 FROM :STMT;
   //
   //************************************
   // Declare Cursor for STMT           *
   //************************************
   EXEC SQL
    DECLARE C1 CURSOR FOR S1;
   //
   //****************************************************
   // Assign employee number to use in select statement *
   //****************************************************
   EMPNUM = '000110';

   //*********************
   // Open Cursor        *
   //*********************
   EXEC SQL
    OPEN C1 USING :EMPNUM;
   //
   //**********************************************
   // Fetch record and put value of               *
   // LASTNAME into NAME                          *
   //**********************************************
   EXEC SQL
     FETCH C1 INTO :NAME; 

答案 1 :(得分:1)

您无法准备抓取。您可以准备用于定义游标的SQL语句。所以它看起来像这样:

dcl-s stmt      Varchar(256) Inz('');

exec sql declare S1 statement;
exec sql declare C1 cursor for S1;

stmt = 'select * from customer where cusno = ?';
exec sql prepare S1 from :stmt;
exec sql open C1 using :customerNumber;

exec sql fetch C1 into :customerDS;
dow %subst(sqlstate:1:2) = '00'
    or %subst(sqlstate:1:2) = '01';

  ... process it here ...

  exec sql fetch C1 into :customerDS;
enddo;
exec sql close C1;

注意这里没有错误检查。你真的想在所有可执行的sql语句上做到这一点。另请注意,exec sql declare ...语句不可执行。甚至不是declare C1 cursor。我通常会把我的sql放在自己的程序中。准备和开放将在一个程序中进行,在另一个程序中进行,而在另一个程序中进行结束。

关于在嵌入式sql中使用过程和局部变量的一些注意事项。使用静态游标时,需要将声明放在与open相同的过程中,因为主机变量在declare语句中,并且在执行打开时它们必须是范围内的相同变量。这是因为声明被完全注释掉,并且不生成代码。它不可执行。在这种情况下,主机变量出现在为open打开的代码中。

使用准备好的游标,您不需要像使用静态游标那样将声明放在与打开相同的过程中。这是因为在预准备语句中绑定到参数标记的主变量出现在open语句中。声明可以通过全局声明在程序的头部。毕竟,无论申报地点在何处,它都是一份全球声明。我喜欢明确声明我准备好的陈述,即使你没有。我把它们放在游标声明中。

我通常会让fetch过程返回一个布尔值(指示符)或一个记录计数,这样我就不必在代码中重复调用了。这里确实重复获取,因为我没有使用过程。

最后,我测试错误的一个例外是我在关闭后没有测试错误,因为唯一会抛出的错误是游标没有打开,这不是我脑子里的错误,这就是我完成它时我想要的光标状态。