如果查询没有返回行,如何插入行?

问题描述 投票:0回答:2

我正在尝试创建允许用户输入队列名称的代码。然后,如果在 select 语句中返回行,则插入包含结果的行。如果没有返回行,我希望插入一行并插入“norows”信息。

当我在 Toad 中运行该案例时,出现语法错误,然后出现。如何解决此语法错误?

SELECT CASE
WHEN EXISTS
(SELECT A.QUEUENAME, DECODE(A.SUBCONSTATUS, 0, 'ERROR', 1, 'NEW', 2, 'STARTED', 3, 'WORKING', 4, 'DONE', 5, 'RETRY', 6, 'TIMEOUT', 7, 'EDITED', 8, 'CANCELED', 9, 'HOLD', A.SUBCONSTATUS) STATUS, TRUNC(LASTUPDDTTM),COUNT()
FROM SYSADM.PSAPMSGSUBCON A
where A.SUBCONSTATUS in (0,1,2,4)
AND A.QUEUENAME = '&QUEUENAME'
and TRUNC(LASTUPDDTTM) = TRUNC(SYSDATE)
GROUP BY A.QUEUENAME, DECODE(A.SUBCONSTATUS, 0, 'ERROR', 1, 'NEW', 2, 'STARTED', 3, 'WORKING', 4, 'DONE', 5, 'RETRY', 6, 'TIMEOUT', 7, 'EDITED', 8, 'CANCELED', 9, 'HOLD', A.SUBCONSTATUS), TRUNC(LASTUPDDTTM)
THEN
  INSERT INTO NP2DBA.NP2_IB_MSGSTATUS
  SELECT A.QUEUENAME, DECODE(A.SUBCONSTATUS, 0, 'ERROR', 1, 'NEW', 2, 'STARTED', 3, 'WORKING', 4, 'DONE', 5, 'RETRY', 6, 'TIMEOUT', 7, 'EDITED', 8, 'CANCELED', 9, 'HOLD', A.SUBCONSTATUS) STATUS, CURRENT_TIMESTAMP,COUNT()
  FROM SYSADM.PSAPMSGSUBCON A
  where A.SUBCONSTATUS in (0,1,2,4)
  AND A.QUEUENAME = '&QUEUENAME'
  and TRUNC(LASTUPDDTTM) = TRUNC(SYSDATE)
  GROUP BY A.QUEUENAME, DECODE(A.SUBCONSTATUS, 0, 'ERROR', 1, 'NEW', 2, 'STARTED', 3, 'WORKING', 4, 'DONE', 5, 'RETRY', 6, 'TIMEOUT', 7, 'EDITED', 8, 'CANCELED', 9, 'HOLD', A.SUBCONSTATUS), TRUNC(LASTUPDDTTM)
ELSE
  INSERT INTO NP2DBA.NP2_IB_MSGSTATUS
  VALUES ('&QUEUENAME','NOROWS',CURRENT_TIMESTAMP, '0')
END
/
oracle-database
2个回答
1
投票

Oracle SQL 中不使用 CASE 进行流控制(如 IF-ELSE)。要执行所需的操作(如果存在记录,则插入记录,否则插入默认值),您必须结合使用 PL/SQL 或带有 IF 或 MERGE 的单独 SQL 语句。


0
投票

您无法在 case 表达式中或查询中进行插入。

您可以使用 PL/SQL 块来查询行是否存在,然后决定执行哪个插入,但通常仅当纯 SQL 无法完成某些操作时才应使用 PL/SQL。并且合并在这里并不起作用,因为您想要插入数据是否存在,并且在不同的表中。

您可以使用一个查询进行一次插入,该查询将主查询和生成“NOROWS”数据的第二个查询结合在一起,可以使用

NOT EXISTS
子句,以便仅在主查询找不到行时才找到行:

INSERT INTO NP2DBA.NP2_IB_MSGSTATUS
SELECT
  A.QUEUENAME,
  DECODE(A.SUBCONSTATUS,
    0, 'ERROR',
    1, 'NEW',
    2, 'STARTED',
    3, 'WORKING',
    4, 'DONE',
    5, 'RETRY',
    6, 'TIMEOUT',
    7, 'EDITED',
    8, 'CANCELED',
    9, 'HOLD',
    A.SUBCONSTATUS) STATUS,
  CURRENT_TIMESTAMP,
  COUNT(*)
FROM SYSADM.PSAPMSGSUBCON A
WHERE A.SUBCONSTATUS in (0,1,2,4)
AND A.QUEUENAME = '&QUEUENAME'
AND LASTUPDDTTM >= CAST(TRUNC(SYSDATE) AS TIMESTAMP)
GROUP BY A.QUEUENAME, A.SUBCONSTATUS
UNION ALL
SELECT
  '&QUEUENAME' QUEUENAME,
  'NOROWS' STATUS,
  CURRENT_TIMESTAMP,
  0
FROM DUAL
WHERE NOT EXISTS (
  SELECT null
  FROM SYSADM.PSAPMSGSUBCON A
  WHERE A.SUBCONSTATUS in (0,1,2,4)
  AND A.QUEUENAME = '&QUEUENAME'
  AND LASTUPDDTTM >= CAST(TRUNC(SYSDATE) AS TIMESTAMP)
)

或者作为子查询,在联合的每个分支中都有一个标志和一个

FETCH FIRST ROW WITH TIES
子句 (12c+),如果第一个分支中有任何行,它将停止返回“NOROWS”行:

INSERT INTO NP2DBA.NP2_IB_MSGSTATUS
SELECT
  QUEUENAME, STATUS, CURRENT_TIMESTAMP, MSG_COUNT
FROM (
  SELECT
    1 ROWTYPE,
    A.QUEUENAME,
    DECODE(A.SUBCONSTATUS,
      0, 'ERROR',
      1, 'NEW',
      2, 'STARTED',
      3, 'WORKING',
      4, 'DONE',
      5, 'RETRY',
      6, 'TIMEOUT',
      7, 'EDITED',
      8, 'CANCELED',
      9, 'HOLD',
      A.SUBCONSTATUS) STATUS,
    COUNT(*) MSG_COUNT
  FROM SYSADM.PSAPMSGSUBCON A
  WHERE A.SUBCONSTATUS in (0,1,2,4)
  AND A.QUEUENAME = '&QUEUENAME'
  AND LASTUPDDTTM >= CAST(TRUNC(SYSDATE) AS TIMESTAMP)
  GROUP BY A.QUEUENAME, A.SUBCONSTATUS
  UNION ALL
  SELECT
     2 ROWTYPE,
    '&QUEUENAME' QUEUENAME,
    'NOROWS' STATUS,
    0 MSG_COUNT
  FROM DUAL
)
ORDER BY ROWTYPE
FETCH FIRST ROW WITH TIES

fiddle 显示插入数据之前和之后运行的两个版本。 (当然,数据是非常组成的,并且由于 db<>fiddle 不支持替换变量,我使用

&QUEUENAME
作为实际的文字队列名称,这样就不需要在查询中更改它.)

我还简化了 group-by 子句,并更改了日期/时间过滤器,因此不需要使用

TRUNC()
操作列值 - 假设该值不能在 now 之前,这似乎合理...

© www.soinside.com 2019 - 2024. All rights reserved.