UPDATE SET子句中的嵌套CASE语句

时间:2017-01-25 15:54:03

标签: sql oracle sql-update case

我试图根据一组条件切换一个值,我注意到在我的UPDATE表达式的SET子句中有一个嵌套的CASE语句,列没有更新。

当存在简单的CASE表达式时,列似乎正在更新。但是,对于此示例中的OVERRIDDEN_CHECK_NUMBER和OVERRIDDEN_AMOUNT,列不会更新。

UPDATE中的OVERRIDDEN_DATE,OVERRIDDEN_USER_ID,CHECK_NO和AMOUNT列正在更新而不会出现问题。

有谁可以告诉我为什么OVERRIDDEN_CHECK_NUMBER和OVERRIDDEN_AMOUNT不会在此UPDATE语句中更新?

嵌套的CASE语句是否在UPDATE表达式的SET子句中没有用?

SQL示例

UPDATE WAREHOUSE.BANK_STATEMENT_ACTIVITY
    SET OVERRIDDEN_CHECK_NO       = --(CASE :btn                                          
                                        (CASE WHEN (:btn = '1') THEN CASE WHEN '141973' = '141973' THEN NULL
                                                                           WHEN '141973' != '999999' THEN LPAD(TRIM(141973), 12, '0')
                                                                      END
                                        WHEN (:btn = '2') THEN '1740 - Previously Paid Warrant'
                                        ELSE NULL
                                    END),
        OVERRIDDEN_AMOUNT         = --(CASE :btn
                                        (CASE WHEN (:btn = '1') THEN CASE WHEN 253.20 = 253.20 THEN NULL
                                                                           WHEN 253.20 != 999.99 THEN LPAD(TRIM(253.20), 12, '0')
                                                                      END
                                        WHEN (:btn = '2') THEN NULL
                                        ELSE NULL
                                    END),
        OVERRIDDEN_DATE           = SYSDATE,
        OVERRIDDEN_USER_ID        = 1009,
        CHECK_NO                  = (CASE :btn
                                        WHEN '1' THEN LPAD(TRIM(999999), 12, '0')
                                        WHEN '2' THEN '142775'
                                        ELSE NULL
                                        END),
        AMOUNT                    = (CASE :btn
                                        WHEN '1' THEN TRIM(78.60)
                                        WHEN '2' THEN TRIM(253.20)
                                        ELSE NULL
                                        END)
        WHERE TO_NUMBER(CHECK_NO) = (CASE :btn
                                        WHEN '1' THEN '141973'
                                        WHEN '2' THEN '142775'
                                        ELSE NULL
                                    END)
        AND AMOUNT                = (CASE :btn
                                        WHEN '1' THEN 78.60
                                        WHEN '2' THEN 253.20
                                        ELSE NULL
                                    END)
        AND TRUNC(LOAD_DATE)      = (CASE :btn
                                        WHEN '1' THEN TRUNC(LOAD_DATE)
                                        WHEN '2' THEN (SELECT (MAX(LOAD_DATE)) FROM WAREHOUSE.BANK_STATEMENT_ACTIVITY)
                                        ELSE NULL
                                        END)
        AND BANKACCTNO            = (SELECT LONGDESC 
                                     FROM TCMS.COMPLEMENTARY_VALIDATIONS
                                     WHERE TEXTCODE = 'BANKACCT'
                                     AND CODE = 80);

修改

修复了@mathguy通过编辑器指出更新查询的逻辑问题。但是,当通过PL / SQL pacakge执行此操作时,表更新失败。

以下是更新前的内容:

Before - result

她的结果是:

After - result

它们完全相同。

这是实际的套餐程序:

PROCEDURE UpdateBankStatementActivity( btn IN VARCHAR2)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE( 'UpdateBankStatementActivity - btn: ' || btn );
DBMS_OUTPUT.PUT_LINE( 'UpdateBankStatementActivity - bsa_rec.OVERRIDDEN_CHECK_NO: ' || bsa_rec.OVERRIDDEN_CHECK_NO || CHR(10) ||
                                                    'bsa_rec.OVERRIDDEN_AMOUNT: ' || bsa_rec.OVERRIDDEN_AMOUNT || CHR(10) ||
                                                    'bsa_rec.CHECK_NO: ' || bsa_rec.CHECK_NO || CHR(10) ||
                                                    'bsa_rec.AMOUNT: ' || bsa_rec.AMOUNT || CHR(10) ||
                                                    'bsa_rec.LOAD_DATE:' || bsa_rec.LOAD_DATE );
    UPDATE WAREHOUSE.BANK_STATEMENT_ACTIVITY
    SET OVERRIDDEN_CHECK_NO       = --(CASE :btn                                          
                                        (CASE WHEN (btn = '1') THEN CASE WHEN bsa_rec.OVERRIDDEN_CHECK_NO = bsa_rec.CHECK_NO THEN NULL
                                                                         WHEN bsa_rec.OVERRIDDEN_CHECK_NO != bsa_rec.CHECK_NO THEN LPAD(TRIM(bsa_rec.OVERRIDDEN_CHECK_NO), 12, '0')
                                                                    END
                                        WHEN (btn = '2') THEN '1740 - Previously Paid Warrant'
                                        ELSE NULL
                                    END),
        OVERRIDDEN_AMOUNT         = --(CASE :btn
                                        (CASE WHEN (btn = '1') THEN CASE WHEN bsa_rec.OVERRIDDEN_AMOUNT = bsa_rec.AMOUNT THEN NULL
                                                                         WHEN bsa_rec.OVERRIDDEN_AMOUNT != bsa_rec.AMOUNT THEN LPAD(TRIM(bsa_rec.OVERRIDDEN_AMOUNT), 12, '0')
                                                                    END
                                        WHEN (btn = '2') THEN NULL
                                        ELSE NULL
                                    END),
        OVERRIDDEN_DATE           = SYSDATE,
        OVERRIDDEN_USER_ID        = bsa_rec.OVERRIDDEN_USER_ID,
        CHECK_NO                  = (CASE btn
                                        WHEN '1' THEN LPAD(TRIM(bsa_rec.CHECK_NO), 12, '0')
                                        WHEN '2' THEN LPAD(TRIM(bsa_rec.CHECK_NO), 12, '0')
                                        ELSE NULL
                                        END),
        AMOUNT                    = (CASE btn
                                        WHEN '1' THEN TRIM(bsa_rec.OVERRIDDEN_AMOUNT)
                                        WHEN '2' THEN TRIM(bsa_rec.AMOUNT)
                                        ELSE NULL
                                        END)
        WHERE TO_NUMBER(CHECK_NO) = (CASE btn
                                        WHEN '1' THEN bsa_rec.OVERRIDDEN_CHECK_NO
                                        WHEN '2' THEN bsa_rec.CHECK_NO
                                        ELSE NULL
                                    END)
        AND AMOUNT                = (CASE btn
                                        WHEN '1' THEN bsa_rec.OVERRIDDEN_AMOUNT
                                        WHEN '2' THEN bsa_rec.AMOUNT
                                        ELSE NULL
                                    END)
        AND TRUNC(LOAD_DATE)      = (CASE btn
                                     WHEN '1' THEN  TRUNC(bsa_rec.LOAD_DATE)
                                     WHEN '2' THEN (SELECT MAX(LOAD_DATE) FROM WAREHOUSE.BANK_STATEMENT_ACTIVITY)
                                     ELSE NULL
                                     END)
        AND BANKACCTNO            = (SELECT LONGDESC 
                                     FROM TCMS.COMPLEMENTARY_VALIDATIONS
                                     WHERE TEXTCODE = 'BANKACCT'
                                     AND CODE = 80);

    COMMIT;
END UpdateBankStatementActivity;

第一个SQL CODE代码段中的参数值与PL / SQL块中的参数一致。

1 个答案:

答案 0 :(得分:1)

你是什么意思"没有更新"?

case时,嵌套:btn = '1'表达式中存在明显的逻辑缺陷。即,"内部"的第一个分支。 case表达式始终计算为TRUE,因此"更新值"每次通过null时都会:btn = '1'。这是你注意到的问题吗?然后:对于overridden_amount,结果将始终为null,因为这样;对于overridden_check_no,当且仅当null时,它不会是:btn = '2'

请注意,您可以编写"外部" case表达式使用与简单表达式相同的语法:case :btn when '1' then case .... end else ... end

编辑:回答您修改后的问题(可能)。我不确定我是否可以完全遵循逻辑;但是示例中发生了什么(假设您使用btn = '1'调用过程是这样的:

原始表格中overridden_check_nooverridden_amount都是null。在两列的嵌套(内部)case表达式中,您可以检查两列,其中包含=!=如果其中一个条款为true,那么的测试都不是null!因此,case评估会转到else子句,或者不包括else时,默认值为nullupdate实际上确实有效,它只是将值更新为null,因为没有一个"实际分支"在评估为case的内部true语句中。

但是,如果您只是直接从编辑器中将其作为独立的SQL update运行,那么您可以这样说。我想知道这是怎么可能的,除非 - 再次 - 程序中的代码与编辑器中的代码不同。