用oracle中的默认值替换空值

Replace nulls by default values in oracle

请关注以下oracle新手案例:

Table "X" 包含客户数据:

ID  Variable_A  Variable_B  Variable_C  Variable_D
--------------------------------------------------
1   100         null        abc         2003/07/09
2   null        2           null        null

Table "Dictionary" 包含我们可以视为客户数据的默认值:

Variable_name  Default_Value
----------------------------
Variable_A     50
Variable_B     0
Variable_C     text
Variable_D     sysdate

目标是通过给定 ID 检查 "X" 中的行,并将空值替换为 "Dictionary" 中的默认值。具体问题是关于最佳解决方案,因为目前我自己的解决方案在于使用循环和 MERGE INTO 语句,我认为这不是最佳的。此外,有必要使用灵活的代码,而不必在将新列添加到 "X".

时更改它

直接的方法是使用

update X set
  variable_a = coalesce(variable_a, (select default_value from Dictionary where name = 'Variable_A')),
  variable_b = coalesce(variable_b, (select default_value from Dictionary where name = 'Variable_B')),
  ... and so on ...

一般应该够快了。

由于您不知道 table X 的哪些字段将为空,因此您应该为每一行提供每个默认值。由于 X 的每个字段可能是不同的数据类型,因此 Dictionary table 应该在适当类型的字段中具有每个默认值。这样的布局如图Fiddle.

显示 X 的每一行完全填充 X 中的值或其默认值的查询变得相对简单。

select  ID,
        nvl( Var_A, da.Int_Val ) Var_A,
        nvl( Var_B, db.Int_Val ) Var_B,
        nvl( Var_C, dc.Txt_Val ) Var_C,
        nvl( Var_D, dd.Date_Val ) Var_D
from    X
join    Dict  da
    on  da.Name = 'VA'
join    Dict  db
    on  db.Name = 'VB'
join    Dict  dc
    on  dc.Name = 'VC'
join    Dict  dd
    on  dd.Name = 'VD';

将其转换为 Update 语句稍微复杂一些,但使用几次后就足够简单了:

update  X
    set (Var_A, Var_B, Var_C, Var_D) =(
        select nvl( Var_A, da.Int_Val ),
               nvl( Var_B, db.Int_Val ),
               nvl( Var_C, dc.Txt_Val ),
               nvl( Var_D, dd.Date_Val )
        from    X InnerX
        join    Dict  da
            on  da.Name = 'VA'
        join    Dict  db
            on  db.Name = 'VB'
        join    Dict  dc
            on  dc.Name = 'VC'
        join    Dict  dd 
            on  dd.Name = 'VD'
        where   InnerX.ID = X.ID )
where   exists(
        select  1
        from    X
        where   Var_A is null
            or  Var_B is null
            or  Var_C is null
            or  Var_D is null );

这个有问题。日期类型的默认值为 sysdate,这意味着它将显示填充默认值 table 的日期和时间,而不是执行更新的日期和时间。我认为这不是您想要的。您可以尝试使用动态 sql 使这一切都起作用,但这会复杂得多。对于您想在此处执行的操作来说太复杂了。

我只看到两个现实的选择:要么存储一个有意义的日期作为默认日期(例如 9999-12-31),要么只知道日期类型的每个默认值都是 sysdate 并使用它在你的更新中。这将在上面的更新中通过更改一行来完成:

               nvl( Var_D, sysdate )

并删除最后一个连接。