我一直在尝试在db2中准备一个Fetch语句,如下所示
Stmt = %trim('FETCH EXSQCRS INTO ?');
EXEC SQL PREPARE SQLSTMT2 FROM :STMT ;
EXSQCRS是一个游标。
但这是失败的-104错误。关于如何写这个的任何线索?
答案 0 :(得分:2)
FETCH
不是可以准备的陈述。它只是一个可执行语句。见Actions allowed on SQL statements
动态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过程返回一个布尔值(指示符)或一个记录计数,这样我就不必在代码中重复调用了。这里确实重复获取,因为我没有使用过程。
最后,我测试错误的一个例外是我在关闭后没有测试错误,因为唯一会抛出的错误是游标没有打开,这不是我脑子里的错误,这就是我完成它时我想要的光标状态。