【问题标题】:How to use parameter markers in sql / cobol如何在 sql/cobol 中使用参数标记
【发布时间】:2020-07-01 20:24:30
【问题描述】:

我必须编写一个 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 一个非空白的 vAlue),OPEN 语句返回一个 SQLCODE -313(在 EXECUTE 或 OPEN 语句中指定的主机变量的数量与准备好的SQL语句中出现的参数标记(问号)的数量。)在我看来,主变量和参数标记的数量都是1,那么问题出在哪里?

编辑

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

OPEN SQL_LIST USING DESCRIPTOR :SQLDA

这现在给出 SQLCODE -822。

编辑 2

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

【问题讨论】:

  • 什么平台? z/OS 还是 IBM i?
  • 感谢您的评论。我正在研究 IBM i。
  • 错误消息文本的其余部分是什么?应该给你一个条目号和错误类型value in entry number &1 that is not valid. The incorrect address or value is type &2.

标签: sql db2 cobol


【解决方案1】:

了解平台会有所帮助..

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

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

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

话虽如此,您可能需要考虑静态 SQL 而不是动态 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 将根据文档指定 OPEN…USING DESCRIPTOR descriptor-name。老实说,我从来没有这样做过。

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

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

【讨论】:

  • 感谢您的回复。我正在研究 IBM i。我猜如果参数标记的数量可能不同,第一个选项将不起作用:我应该写 `` OPEN SQL_LIST USING :SQLDA `` 代替吗?第二种选择似乎更好,我也想过。我跳过了它,因为我会在不需要 where 子句时省略它(担心性能,但也许没有什么可担心的,因为静态查询应该比动态查询快)。
  • 阅读该手册时产生了使用参数标记的想法,但也许我在阅读OPEN 语句时不够仔细。请参阅问题的编辑以获取更新。在这个问题中,静态查询就足够了。还有一些其他情况(这里没有提到,它们可能是我的下一个任务)静态查询会更复杂,因此我仍然想学习如何使用此功能。
  • @user8780522 我相信您需要设置SQLD = 1,因为您使用了1个参数标记..
  • SQLDDESCRIBE 语句之后已设置为 1。我在手册上发现每个宿主变量都必须有一个关联的指标变量,并且出现的SQLIND必须设置为指标变量的地址。
猜你喜欢
  • 1970-01-01
  • 2015-05-19
  • 1970-01-01
  • 2022-01-18
  • 2012-05-02
  • 2011-08-18
  • 1970-01-01
  • 1970-01-01
  • 2022-11-27
相关资源
最近更新 更多