【问题标题】:Clubbing update statements using case in oracle在 oracle 中使用 case 合并更新语句
【发布时间】:2017-03-13 14:46:05
【问题描述】:

我正在尝试根据错误情况使用不同的错误代码更新同一列。

更新条件(单独):

UPDATE MEM_SRC_EXTN
SET INT_VALUE_1 =100
WHERE ISNULL(TYPE_VALUE,'') =''
OR ISNULL(TYPE,'') =''
OR ISNULL(VALUE_1,'') =''
OR ISNULL(VALUE_2,'') ='';

UPDATE MEM_SRC_EXTN EXTN
SET INT_VALUE_1=222
WHERE NOT EXISTS 
(SELECT 1
FROM CMC_MEM_SRC SRC 
WHERE EXTN.TYPE_VALUE = SRC.TN_ID);

UPDATE MEM_SRC_EXTN
SET INT_VALUE_1=333 
GROUP BY TYPE_VALUE 
HAVING COUNT(VALUE_1)>1;

由于我必须根据条件将这 3 个更新条件合并为一个,因此它首先检查条件,然后更新列值,而不是每次都触发所有 3 个更新语句。

我想出了这个解决方案,但不确定这是否可行?

UPDATE MEM_SRC_EXTN EXTN
SET INT_VALUE_1 = CASE 
                          WHEN (ISNULL(TYPE_VALUE,'') ='' OR ISNULL(TYPE,'') ='' OR ISNULL(VALUE_1,'') =''OR ISNULL(VALUE_2,'') ='')
                          THEN 100
                          WHEN NOT EXISTS (SELECT 1 FROM CMC_MEM_SRC SRC WHERE EXTN.TYPE_VALUE = SRC.TN_ID)
                          THEN 222
                          WHEN GROUP BY TYPE_VALUE HAVING COUNT(VALUE_1)>1
                          THEN 333
                          ELSE 000
                        END

【问题讨论】:

  • 这确实是正确的做法。如果由于某种原因无法正常工作,请对其进行测试并写回。
  • Oracle 中没有isnull 函数,请改用coalescenvl - 请参阅stackoverflow.com/questions/3523036/…
  • 此外,空字符串在 Oracle 中被视为 NULL。因此,如果 TYPE_VALUENULL,则 NVL(TYPE_VALUE,'') = '' 将是 FALSE。我希望你想要NVL(TYPE_VALUE,'#NULL#') = '#NULL#' 或类似的东西,其中'#NULL#' 是一些不能是TYPE_VALUE 的实际值的通用字符串。
  • 还有WHEN GROUP BY...这根本不对。这个问题需要有人来回答。

标签: oracle


【解决方案1】:

首先你应该使用正确的语句顺序。如果WHEN GROUP BY TYPE_VALUE HAVING COUNT(VALUE_1)>1 是最后一个,那么它应该是第一个。 此外你不能写WHEN GROUP BY TYPE_VALUE HAVING COUNT(VALUE_1)>1。 orcle 中的 = ''= null 相同,它不是 true 也不是 false 使用为 null 您可以将其重写为子查询

UPDATE MEM_SRC_EXTN EXTN
SET INT_VALUE_1 = CASE 
     WHEN exists (SELECT NULL 
                    FROM MEM_SRC_EXTN sub_extn
                   WHERE sub_extn.TYPE_VALUE = EXTN.TYPE_VALUE 
                      OR (sub_extn.TYPE_VALUE is NULL AND EXTN.TYPE_VALUE IS NULL)
                   GROUP BY TYPE_VALUE 
                  HAVING COUNT(VALUE_1)>1)
       THEN 333
     WHEN NOT EXISTS (SELECT 1 
                        FROM CMC_MEM_SRC SRC 
                       WHERE EXTN.TYPE_VALUE = SRC.TN_ID)
       THEN 222
     WHEN TYPE_VALUE is null OR TYPE is null OR VALUE_1 is null OR VALUE_2 is null
       THEN 100
     ELSE 000
     END

但是这个查询很灵活,你可能会使用别的东西。请考虑merge

【讨论】:

    【解决方案2】:

    我会为此考虑使用MERGE 声明。像这样:

    MERGE INTO mem_src_extn t USING 
    ( 
    SELECT mse.rowid row_id,
           CASE WHEN mse.type_value IS NULL OR mse."TYPE" IS NULL OR mse.VALUE_1 IS NULL or mse.VALUE_2 IS NULL THEN 100
                WHEN ( SELECT count(*) FROM cmc_mem_src cms WHERE cms.tn_id = mse.type_value ) = 0 THEN 222
                WHEN count(mse.value_1) over ( partition by type_value ) > 1 THEN 333
           ELSE '000' int_value_1  
    FROM   mem_src_extn mse
    ) u
    ON ( t.rowid = u.row_id )
    WHEN MATCHED THEN UPDATE SET t.int_value_1 = u.int_value_1 WHERE u.inv_value_1 != '000';
    

    MERGE 语句为开发人员带来了额外的好处——您只需运行其中的SELECT 部分即可查看您的结果。这样更容易调试。

    另请注意,您最初的 UPDATE 语句不会将任何内容更新为 000,但您提出的解决方案会。因此,尚不清楚您的要求是什么。由于MERGEUPDATE 子句中的WHERE 子句,我的解决方案不会对000 进行任何更新。如果您想将不满足三个条件中的任何一个的行设置为000,则可以将其删除。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      • 2013-12-15
      相关资源
      最近更新 更多