iSeries:SQLRPGLE 如何为 SELECT 语句中的每条记录调用过程

iSeries: SQLRPGLE How to call a procedure for each record in a SELECT statement

在 SQLRPGLE 程序中,我需要 运行 插入语句以将一些记录复制到另一个已复制记录并分配了新记录 ID 的文件。 为此,我遵循了以下步骤:

1) 制作一个程序原型,每次调用时获取一个新的记录 ID

    D ri_box12        PR            13S 0
    D   wkFileName                  10A   Value
    
2)执行动态SQL语句
    C                   EVAL      SQL_STM='insert into PGMR46/STD05GR0F'
    C                                    +' (select CART, CARV, '
    C                                    +%char(ri_box12('STD05GR0F'))
    C                                    +'  from arasso0f)'
    C/EXEC SQL
    C+ execute immediate :SQL_STM
    C/END-EXEC
    
3) 定义ri_box12过程
    P ri_box12        B
    D ri_box12        PI            13S 0
    D   wkFileName                  10A   Value
    D   wkID          S             13S 0
    C                   DO
** ...some instructions to give wkID a value C ENDDO C Return wkID P E
关键是 ri_box12 只被调用一次,所以所有复制的记录都有相同的 ID;程序的多个 运行 再次复制具有新记录 ID 的所有记录。

我做错了什么或者我错过了什么?

比你厉害

首先,您不需要在这里使用动态 SQL。静态 SQL 可以工作,出于安全和性能原因,首选静态 SQL。

/free    
 exec SQL
   insert into PGMR46/STD05GR0F
     select CART, CARV, ri_box12('STD05GR0F')
     from arasso0f
 end-exec;

但是,为了使 RPGLE 函数的 CALL 起作用,您缺少了一件。

您必须定义所谓的外部用户定义函数 (UDF)。这是一次性步骤。您基本上是在通知 SQL 查询引擎 RPGLE 函数存在以及它的界面是什么样的。

您通常不希望在与 ri_box12() 函数相同的程序中使用上面的 INSERT 语句。通常你会有这样的过程

  1. 创建包含 ri_box12()
  2. 的 *SRVPGM(或 *PGM)
  3. 创建指向 ri_box12() 的 UDF
  4. 创建 program/stored 使用 UDF 的过程

第 3 步是包含您的 INSERT SQL 语句的程序。

第 2 步只是 运行 一个 SQL 语句,如下所示:

create function ri_box12(
  filename char(10)
  ) returns numeric(13,0)
  language RPGLE
  parameter style general
  returns null on null input
  program type sub
  external name 'MYSRVPGM(RIBOX_12)';

您 can/should 还为函数指定了许多其他设置。查看 SQL 参考手册的 CREATE FUNCTION (External Scalar) 部分。

我还强烈推荐阅读 External Procedures, Triggers, and User-Defined Functions on IBM DB2 for i Redbook

不确定 OP 中的函数 ri_box12 是做什么的,但如果只是一个序列号,那么 SQL SEQUENCE 可能是实现该效果的方法;有关示例,请参见以下脚本 SQL:

drop   table qtemp.nbrs ;                        
drop   table qtemp.junk ;                        
drop sequence myseq ;                            
create table qtemp.nbrs (n int)         ;        
insert into  qtemp.nbrs values(10), (20), (30) ; 
create table qtemp.junk (s int, i int)  ;        
create sequence myseq as integer start with 1  ; 
insert into  qtemp.junk                          
 select next value for myseq, n from qtemp.nbrs ;
select * from qtemp.junk
; -- report from the above SELECT query follows:
        S               I
        1              10
        2              20
        3              30

IBM i 7.2->Database->Reference->SQL reference->Concepts->Sequences
IBM i 7.2->Database->Reference->SQL reference->Statements->CREATE SEQUENCE
IBM i 7.2->Database->Reference->SQL reference->Language elements->Expressions->Sequence reference