请关注以下oracle初学者的案例:
表" X"包含客户数据:
ID Variable_A Variable_B Variable_C Variable_D
--------------------------------------------------
1 100 null abc 2003/07/09
2 null 2 null null
表"字典"包含我们可以视为客户数据的默认值:
Variable_name Default_Value
----------------------------
Variable_A 50
Variable_B 0
Variable_C text
Variable_D sysdate
目标是检查" X"中的行。通过给定ID并使用" Dictionary"中的默认值替换空值。具体问题是关于最优解决方案,因为现在我自己的解决方案在于使用MERGE INTO语句循环,我认为这不是最优的。当新列被添加到" X"时,有必要使用灵活的代码,而不应该更改它。
答案 0 :(得分:2)
直接的方法是使用
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 ...
一般来说它应该足够快。
答案 1 :(得分:1)
由于您不知道表X的哪些字段为空,因此您应该为每一行提供每个默认值。并且由于X的每个字段可能是不同的数据类型,因此Dictionary表应在相应类型的字段中具有每个默认值。这种布局显示在 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 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
,这意味着它将显示填充默认表的日期和时间,而不是执行更新的日期和时间。我想,这不是你想要的。您可以尝试使用动态sql完成所有工作,但这会更复杂。你想在这里做什么太复杂了。
我只看到两个现实选项:要么将有意义的日期存储为默认日期(例如9999-12-31),要么只知道日期类型的每个默认日期都是sysdate
并在您的更新。只需更改一行即可在上述更新中完成:
nvl( Var_D, sysdate )
并摆脱最后一次加入。