如何在 sql / cobol 中使用参数标记

How to use parameter markers in sql / cobol

我必须编写一个 COBOL 程序,从文件中读取一些记录并用它们进行一些计算。如果使用非空白过滤器调用例程,则应过滤结果。

我尝试在 SQL 中使用参数标记。这是我的尝试:

    100        IDENTIFICATION DIVISION.                                                                                 19/11/07
    200        PROGRAM-ID.    MINIMALEX.                                                                                01/07/20
    300        AUTHOR.        ME.                                                                                       01/07/20
    400        DATE-WRITTEN.  JULY 2020.                                                                                01/07/20
    500       *----------------------------------------------------------------*                                        01/07/20
    600       *--- Minimal example.                                         ---*                                        01/07/20
    700       *----------------------------------------------------------------*                                        01/07/20
    800        ENVIRONMENT DIVISION.                                                                                    19/11/07
    900        CONFIGURATION SECTION.                                                                                   19/11/07
   1000        SOURCE-COMPUTER. IBM-AS400.                                                                              19/11/07
   1100        OBJECT-COMPUTER. IBM-AS400.                                                                              19/11/07
   1200        SPECIAL-NAMES. DECIMAL-POINT IS COMMA.                                                                   28/12/10
   1300       *----------------------------------------------------------------*                                        01/07/20
   1400        INPUT-OUTPUT SECTION.                                                                                    19/11/07
   1500        FILE-CONTROL.                                                                                            19/11/07
   1600       *----------------------------------------------------------------*                                        19/11/07
   1700        DATA DIVISION.                                                                                           19/11/07
   1800        FILE SECTION.                                                                                            19/11/07
   1900       *----------------------------------------------------------------*                                        19/11/07
   2000        WORKING-STORAGE SECTION.                                                                                 19/11/07
   2100       *--- Variables for SQL.                                                                                   01/07/20
   2200            EXEC SQL                                                                                             01/07/20
   2300              INCLUDE SQLCA                                                                                      01/07/20
   2400            END-EXEC.                                                                                            01/07/20
   2500            EXEC SQL                                                                                             01/07/20
   2600              INCLUDE SQLDA                                                                                      01/07/20
   2700            END-EXEC.                                                                                            01/07/20
   2800                                                                                                                 01/07/20
   2900        01  WK-NAME                        PIC X(80).                                                            01/07/20
   3000        01  WK-LASTNAME                    PIC X(80).                                                            01/07/20
   3100        01  WK-SELECT                      PIC X(34).                                                            01/07/20
   3200        01  WK-WHERE                       PIC X(65).                                                            01/07/20
   3300        01  WK-STATEMENT                   PIC X(100).                                                           01/07/20
   3400       *----------------------------------------------------------------*                                        01/07/20
   3500        LINKAGE SECTION.                                                                                         19/11/07
   3600        01  LK-NAME                        PIC X(80).                                                            01/07/20
   3700       *----------------------------------------------------------------*                                        01/07/20
   3800        PROCEDURE DIVISION USING LK-NAME.                                                                        01/07/20
   3900       *----------------------------------------------------------------*                                        01/07/20
   4000        A01-START.                                                                                               01/07/20
   4100       *--- Create and insert data into file.                                                                    01/07/20
   4200            EXEC SQL                                                                                             01/07/20
   4300                 DROP TABLE QTEMP/T                                                                              01/07/20
   4400            END-EXEC.                                                                                            01/07/20
   4600            EXEC SQL                                                                                             01/07/20
   4700                 CREATE TABLE QTEMP/T                                                                            01/07/20
   4800                        (NAME CHAR (80), LASTNAME CHAR (80))                                                     01/07/20
   4900            END-EXEC.                                                                                            01/07/20
   5100            EXEC SQL                                                                                             01/07/20
   5200                 INSERT INTO QTEMP/T VALUES ("ALFRED", "HITCHCOCK")                                              01/07/20
   5300            END-EXEC.                                                                                            01/07/20
   5500                                                                                                                 01/07/20
   5600            MOVE 'SELECT NAME, LASTNAME FROM QTEMP/T' TO WK-SELECT.                                              01/07/20
   5700                                                                                                                 21/03/08
   5800            MOVE SPACES TO WK-WHERE.                                                                             01/07/20
   5900            MOVE 0 TO SQLN.                                                                                      01/07/20
   6000                                                                                                                 01/07/20
   6100            IF LK-NAME NOT = SPACES                                                                              01/07/20
   6200               STRING 'WHERE NAME LIKE ("%" CONCAT '                                                             01/07/20
   6300                      'TRIM(CAST(? AS CHAR(80))) CONCAT "%")'                                                    01/07/20
   6400                      DELIMITED BY SIZE INTO WK-WHERE                                                            01/07/20
   6500               ADD 1 TO SQLN                                                                                     01/07/20
   6600            END-IF.                                                                                              01/07/20
   6700                                                                                                                 28/04/08
   6800            STRING WK-SELECT DELIMITED BY SIZE                                                                   01/07/20
   6900                   ' '       DELIMITED BY SIZE                                                                   01/07/20
   7000                   WK-WHERE  DELIMITED BY '   ' INTO WK-STATEMENT                                                01/07/20
   7100            END-STRING.                                                                                          21/04/08
   7200                                                                                                                 30/06/20
   7300            EXEC SQL                                                                                             30/06/20
   7400                 PREPARE STMT FROM :WK-STATEMENT                                                                 01/07/20
   7500            END-EXEC.                                                                                            30/06/20
   7700            EXEC SQL                                                                                             30/06/20
   7800                 DESCRIBE INPUT STMT INTO :SQLDA                                                                 01/07/20
   7900            END-EXEC.                                                                                            30/06/20
   8100                                                                                                                 21/04/08
   8200       *--- Setting values for SQLDA.                                                                            01/07/20
   8300            IF LK-NAME NOT = SPACES                                                                              01/07/20
   8400               SET SQLDATA(1) TO ADDRESS OF LK-NAME                                                              01/07/20
   8500            END-IF.                                                                                              01/07/20
   8600                                                                                                                 30/06/20
   8700            EXEC SQL                                                                                             21/04/08
   8800                 DECLARE SQL_LIST CURSOR FOR STMT                                                                01/07/20
   8900            END-EXEC.                                                                                            21/04/08
   9000                                                                                                                 21/04/08
   9100            EXEC SQL                                                                                             21/04/08
   9200                 OPEN SQL_LIST                                                                                   01/07/20
   9300            END-EXEC.                                                                                            21/04/08
   9500                                                                                                                 21/04/08
   9600        A01-FETCH.                                                                                               01/07/20
   9700            EXEC SQL                                                                                             01/07/20
   9800                 FETCH NEXT FROM SQL_LIST INTO :WK-NAME, :WK-LASTNAME                                            01/07/20
   9900            END-EXEC.                                                                                            01/07/20
  10100            IF SQLCODE NOT = 0                                                                                   01/07/20
  10200               GO TO A01-CLOSE                                                                                   01/07/20
  10300            END-IF.                                                                                              01/07/20
  10400                                                                                                                 01/07/20
  10500       *--- Do some stuff with the fetched data, then fetch next row.                                            01/07/20
  10600            GO TO A01-FETCH.                                                                                     01/07/20
  10700                                                                                                                 21/04/08
  10800        A01-CLOSE.                                                                                               01/07/20
  10900            EXEC SQL                                                                                             13/02/20
  11000                 CLOSE SQL_LIST                                                                                  01/07/20
  11100            END-EXEC.                                                                                            13/02/20
  11300                                                                                                                 13/02/20
  11400        A01-END.                                                                                                 01/07/20
  11500            GOBACK.                                                                                              01/07/20

不幸的是,当我 运行 程序(给 LK-NAME 一个非空白的值)时,OPEN 语句 returns a SQLCODE -313 (The number of EXECUTE 或 OPEN 语句中指定的主机变量与准备好的 SQL 语句中出现的参数标记(问号)的数量不同。)在我看来,主机变量和参数标记的数量都是1、问题出在哪里?

编辑

根据 Charles 的建议,第 9200 行更改为

OPEN SQL_LIST USING DESCRIPTOR :SQLDA

这现在给出 SQLCODE -822。

编辑 2

经过进一步研究,我了解到每个宿主变量必须与链接部分中的指示变量相关联,并且 SQLIND 的出现必须指向这些指示变量的地址。谢谢@Charles

了解该平台会有所帮助..

但是,我希望看到您打算在 open 语句中的参数生成器中使用的变量。

EXEC SQL
  OPEN SQL_LIST USING :LK-NAME
END-EXEC.

open语句是用来替换参数标记的值被替换的地方。

话虽如此,您可能需要考虑静态 SQL 而不是动态的。

静态SQL不需要准备...它只是看起来像

EXEC SQL
  DECLARE SQL_LIST CURSOR FOR
   SELECT NAME, LASTNAME FROM QTEMP/T
   WHERE :LK-NAME = ' '
         OR NAME LIKE ( '%' CONCAT TRIM(:LK-NAME) CONCAT '%')
END-EXEC.

EXEC SQL
  OPEN SQL_LIST
END-EXEC.

请注意,即使在这里,LK-NAME 的值也是在打开游标时传入的,DECLARE CURSOR 确实是一个编译时语句。

编辑
您可以使用描述符区域,如果这种情况下打开会根据文档指定 OPEN…USING DESCRIPTOR descriptor-name。老实说,我从来没有这样做过。

您已阅读 embedded SQL programming 手册,正确吗?

是的,通常静态语句更快。只要与动态版本相比不是太复杂即可。