用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 )
并删除最后一个连接。
请关注以下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 )
并删除最后一个连接。