DB2、PL/SQL 和游标(IBM 不遵循自己的帮助页面)

DB2, PL/SQL and cursors (IBM doesn't follow its own help pages)

DB2,版本 10.5。

我的光标是这样的:

declare stat cursor for select record_type, sequence_code from my_status fetch first 10 rows only;

任何使用 IBM 网页上记录的 FOR 结构遍历它的尝试,例如

for s in stat do
    call dbms_output.put_line ('In the cursor loop');
end for;

DB21034E 命令作为 SQL 语句处理,因为它不是 有效的命令行处理器命令。在 SQL 处理期间它返回: SQL0104N 在“rst 10 rows only; 之后发现意外标记 "for" "。预期的标记可能包括:""。LINE NUMBER=9。 SQLSTATE=42601.

所以我尝试在一个循环中进行显式打开和获取,这很有效——但它会一直持续下去(即当它到达 10 条记录的最后一条时没有错误和中止)如果我没有在循环中放入明确的计数器。显示数据中的字段证明它正在循环 1、2、3....9、10、10、10、10、10。

所以我尝试添加 "if stat%FOUND" 在循环中并收到此错误:

DB21034E 命令作为 SQL 语句处理,因为它不是 有效的命令行处理器命令。在 SQL 处理期间它返回: SQL0104N 在 "ence_code; if stat" 之后发现了意外的标记“%”。 预期标记可能包括:"IS"。行号=24。 SQL状态=42601

我什至尝试了一个 CASE 语句来检查 FOUND / NOTFOUND 状态并得到了类似的错误:

case when stat%NOTFOUND then
    call dbms_output.put_line('In case');
end case;

DB21034E 命令作为 SQL 语句处理,因为它不是 有效的命令行处理器命令。在 SQL 处理期间它返回: SQL0104N 在“case when stat”之后发现意外标记“%”。 预期标记可能包括:"IN"。行号 = 30。 SQL状态=42601

将其更改为 stat.%NOTFOUND(% 之前的一个句点)让我得到了这个:

DB21034E 命令作为 SQL 语句处理,因为它不是 有效的命令行处理器命令。在 SQL 处理期间它返回: SQL0104N 在 " case 之后发现了意外的标记 "stat.%NOTFOUND" when”。预期的标记可能包括:“”。LINE 数字=30。 SQL状态=42601

我尝试了“exit when stat%NOTFOUND”,它是从 IBM 支持页面逐字记录的。这让我遇到了类似的错误:

DB21034E 命令作为 SQL 语句处理,因为它不是 有效的命令行处理器命令。在 SQL 处理期间它返回: SQL0104N 在“ ”之后发现意外标记 "EXIT"。 预期的标记可能包括:“”。行号=23。 SQL状态=42601

注释掉这些不同位的完整代码块工作正常,除了在数据用完时无法终止:

set serveroutput on@

begin
    declare v_counter int default 0;
    declare v_record_type char(1);
    declare v_sequence_code int;

    declare stat cursor for select record_type, sequence_code from my_status fetch first 10 rows only;

    -- for s in stat do
    --     call dbms_output.put_line ('In the cursor loop');
    -- end for;

    open stat;

    fetch from stat into v_record_type, v_Sequence_code;

    set v_counter = 0;
    while v_counter < 12 do
        call dbms_output.put_line('in loop');
        call dbms_output.put_line('Record: '||v_record_type||' '||v_sequence_code);
        set v_counter = v_counter + 1;
        call dbms_output.put_line ('Counter: '||v_counter);
        fetch from stat into v_record_type, v_sequence_code;
        --if stat%FOUND then
        -- call dbms_output.put_line ('Yay, found!');
        --end if;
    --if stat%NOTFOUND then
    --      exit;
    --end if;
    --case when stat%NOTFOUND then
    --    call dbms_output.put_line('In case');
    --end case;
    --EXIT WHEN stat%NOTFOUND;
    end while;
    close stat;
END -- end procedure
@
set serveroutput off@

DB2 for LUW 支持两种不同的 PSM 方言:本机 DB2 SQL PL and Oracle-compatible PL/SQL

由于 SQL PL 一直存在,它的语句包含在文档中的常规 SQL 参考中。 PL/SQL 支持是在 2010 年左右添加的,其语法在单独的部分(上面链接)中进行了描述。您需要注意不要将两者混用,因为程序块只能使用两种方言中的一种,而不能在同一块中同时使用这两种方言。许多语句中存在一定的句法差异,因此在选择要使用的方言后,应注意参考手册中的适当部分。

语法检测或多或少是根据结构自动进行的。在 DB2 SQL PL 中,DECLARE 语句出现在块内,而在 PL/SQL 中,它们在块外。因此,如果您的块以

开头
BEGIN
DECLARE something;
...
END

假定包含 SQL PL 语句,如果编译器遇到 PL/SQL 语句,则会抛出语法错误。

当运行您的程序使用 DB2 命令行处理器时,您可以使用命令 SET SQLCOMPAT {DB2|PLSQL} 来显式指示方言。