COBOL游标在WHERE子句中使用IN运算符

时间:2017-03-01 18:39:45

标签: sql oracle cobol where-in

我有一个问题,我似乎无法弄清楚并想知道它是否是环境的限制,或者是我没想过的简单。

我在AIX中运行,在程序中使用Microfocus Cobol和嵌入式Oracle SQL。

今天,这个SQL针对生产运行的整个表运行,这是按照设计的。当为生产测试系统运行相同的程序时,我们不需要返回一整套结果......我们只需要为该生产测试运行中的客户端返回的记录。

因此,很容易在SQL中添加一个语句来限制它,如下所示:

AND OLM.SYS_TX IN ('8220,8245,8993')

如果我可以将值放入查询中,那就可以了。

问题是我们永远不知道每次运行中会有多少这4位客户端值。可能是一个,可能是其中的30个。在我们开始每次生产测试之前,我们都不知道。

我的解决方案是在这些数字的AIX Korn Shell脚本中创建一个文件,通过ENVIRONMENT-NAME变量接受它们,在程序内部格式化它们,然后使用该格式化字段,将它们传递到COBOL模块SQL就是这样:

AND HIT.SYS_TX IN (:WS-CLIENT-NOS)

但是,我无法让SQL识别该查询中的客户端NO!

示例:

Korn Shell Script准备一个包含以下内容的字段:

8220,8396,8529,8685,8499,8218,8383,8150,8778,8255,8773,8993,8299

COBOL程序接受此行,并格式化要在SQL中使用的新行 我已经通过上面的数字循环计算我有多少非空格字符,然后我使用STRING命令格式化在SQL中使用的新行。所以在格式化后我有这个:

'8220,8396,8529,8685,8499,8218,8383,8150,8778,8255,8773,8993,8299'

位于WORKING STORAGE字段 - WS-CLIENT-NOS

该字段用于以下CURSOR:

EXEC SQL DECLARE PRETEST_EXT_HIT_LIST_CSR CURSOR FOR
SELECT HIT.ACCOUNT_NUMBER,
      HIT.SYS_TX,
      HIT.PRIN_TX,
      LPAD(NVL(RANK, 99999),5, 0),
      NON_OPTIONAL,
      LPAD(LOC.LOCATION_ID, 10, 0),
      LPAD (TRIM (ITEM_ID), 10, '0'),
      TO_CHAR (HIT.START_DT, 'YYYYMMDD'),
      EXT_CLIENT_HIT_LIST_PK
  FROM OLM_MSG_MASTER OMM,
       EXT_CLIENT_HIT_LIST HIT,
       OLM_LOCATIONS LOC
  WHERE DECODE(TRIM(TRANSLATE(item_id,'0123456789',' ')),
               NULL, 'number','contains char') = 'number'
    AND LOC.OLM_LOCATIONS_PK = OMM.OLM_LOCATIONS_FK
    AND OLM_MSG_MASTER_PK = ITEM_ID
    AND APPLICATION_ID = 'MMSG'
    AND HIT.START_DT <=
            TO_DATE (:HV-PROCESS-DATE, 'MMDDYYYY')
    AND (HIT.END_DT IS NULL
      OR HIT.END_DT >=
            TO_DATE (:HV-PROCESS-DATE, 'MMDDYYYY'))
    AND HIT.SYS_TX IN (:WS-CLIENT-NOS)    <============================
ORDER BY HIT.SYS_TX, HIT.PRIN_TX, HIT.ACCOUNT_NUMBER,
         ITEM_ID
END-EXEC.

但是Query不会返回任何结果。

  • 如果我将相同的数据硬编码到IN('')结构中,那么我得到了 结果,所以我的结构和格式都很好。
  • 如果我将''标记硬编码到光标而不是光标中 工作 - 存储领域我没有结果。
  • 如果我将()放在工作存储字段中而不是硬编码 SQL然后它将无法编译。
  • 如果我将关系运算符更改为'='而不是“IN”并使用a 单值而不是它会拉结果。
  • 如果我对它进行硬编码以连接大量“OR”语句,它将起作用 并拉取结果。但这对COBOL来说并不实用。
  • 但是,如果我尝试将我的正确(据称)格式化的数据行 进入那个“IN”条款它不起作用!

任何帮助或技巧都将非常感谢!即使这是无法做到的事情!

标记

2 个答案:

答案 0 :(得分:1)

在我看来,最好的方法是创建一个表来放入你的4位数字,然后简单地连接到这个表。它可能更容易,性能更好,因为优化器可以很好地获得正确的基数。 有几种方法可以实现这个

  1. 使用全球临时表(GTT);会话私有。
  2. 该表具有(例如&#34; session&#34;)标识符,该标识符是连接键的一部分。

答案 1 :(得分:0)

问题是这句话:

HIT.SYS_TX IN (:WS-CLIENT-NOS)

实际上相当于:

HIT.SYS_TX = :WS-CLIENT-NOS

相反,您可以使用like或正则表达式:

:WS-CLIENT-NOS '%,' || HIT.SYS_TX || ',%'

regexp_like(HIT.SYS_TX, '^' || replace(:WS-CLIENT-NOS, ',', '|') || '$')

实际上还有其他方法可以将列表转换为某种表格。但是,上述方法仅涉及更改一行代码。