Sql 仅合并源中的非空字段,保留目标中的其他字段不变
真实数据有更多的列。示例目标表具有唯一的ID字段。数据字段具有现有数据。需要更新记录,但只有部分字段得到更新Sql 仅合并源中的非空字段,保留目标中的其他字段不变,sql,sql-server,tsql,Sql,Sql Server,Tsql,真实数据有更多的列。示例目标表具有唯一的ID字段。数据字段具有现有数据。需要更新记录,但只有部分字段得到更新 -- Original/target table DECLARE @target TABLE ( ID varchar(4) NOT NULL, x int NULL, y int NULL, z int NULL ); INSERT INTO @target (ID, x, y, z) VALUES
-- Original/target table
DECLARE @target TABLE (
ID varchar(4) NOT NULL,
x int NULL,
y int NULL,
z int NULL );
INSERT INTO @target (ID, x, y, z)
VALUES ('A1', NULL, 2, 3),
('A2', 1, 2, NULL),
('C4', 1, 2, 3),
('Z5', 1, 2, 3)
;
--- Updates needed:
DECLARE @updates TABLE (
ID varchar(4) NOT NULL,
x int NULL,
y int NULL,
z int NULL );
INSERT INTO @updates (ID, x, y, z)
VALUES ('A1', NULL , 101, NULL),
('A2', 201, NULL, NULL),
('C4', NULL, NULL, 40),
('Z5', NULL, NULL, 99999)
我需要用户向我发送用于更新/合并到目标表的数据更新。用户可以更新特定字段,但不能更新其他字段。因此,当源表有一个值时,我需要它更新相应的目标字段,但保持其他字段(在源表中为null)不变。仅在源中显式列出(非空)时更改目标字段
例如,ID=A1的源记录的“y”的更新值为101。合并后,我需要A1的目标记录包含:NULL、101、3
我还需要一种方法来“清除”目标中的记录。我想也许可以为记录ID Z5上显示的“99999”之类的数据使用一个特殊值。如果源为“99999”,则将目标字段设置为空
我不会添加任何记录,只会匹配目标中的现有ID
更新:
这两个答案的组合解决方案似乎有效:
update t
set x = coalesce(u.x, t.x),
y = coalesce(u.y, t.y),
z = coalesce(u.z, t.z)
from @target t join
@updates u
on t.id = u.id;
update t
set
x = NULLIF(ISNULL(u.x,t.x),'99999'),
y = NULLIF(ISNULL(u.y,t.y),'99999'),
z = NULLIF(ISNULL(u.z,t.z),'99999')
from @target t join
@updates u
on t.id = u.id;
select * from @target
听起来你需要:
SET Target.Field = NULLIF(ISNULL(Source.Field,Target.Field),'99999')
听起来你需要:
SET Target.Field = NULLIF(ISNULL(Source.Field,Target.Field),'99999')
我在想:
update t
set x = coalesce(u.x, t.x),
y = coalesce(u.y, t.y),
z = coalesce(u.z, t.z)
from @target t join
@updates u
on t.id = u.id;
如果要清除整个记录,我建议在@updates
中添加一个附加标志:
update t
set x = (case when u.clear_record = 1 then null
when u.x is not null then u.x
else t.x
end),
y = (case when u.clear_record = 1 then null
when u.y is not null then u.y
else t.y
end),
z = (case when z.clear_record = 1 then null
when u.z is not null then u.z
else t.z
end)
from @target t join
@updates u
on t.id = u.id;
编辑:
您可以通过使用类似逻辑的特殊值清除特定字段:
update t
set x = (case when u.clear_record = 1 or u.x = '99999' then null
when u.x is not null then u.x
else t.x
end),
y = (case when u.clear_record = 1 or u.y = '9999'9 then null
when u.y is not null then u.y
else t.y
end),
z = (case when z.clear_record = 1 or u.z = '99999' then null
when u.z is not null then u.z
else t.z
end)
from @target t join
@updates u
on t.id = u.id;
但是,对于这样一个特殊值,我不会使用'99999'
。如果值是字符串,我建议使用空字符串('
)或'
或'{null}'
,我想:
update t
set x = coalesce(u.x, t.x),
y = coalesce(u.y, t.y),
z = coalesce(u.z, t.z)
from @target t join
@updates u
on t.id = u.id;
如果要清除整个记录,我建议在@updates
中添加一个附加标志:
update t
set x = (case when u.clear_record = 1 then null
when u.x is not null then u.x
else t.x
end),
y = (case when u.clear_record = 1 then null
when u.y is not null then u.y
else t.y
end),
z = (case when z.clear_record = 1 then null
when u.z is not null then u.z
else t.z
end)
from @target t join
@updates u
on t.id = u.id;
编辑:
您可以通过使用类似逻辑的特殊值清除特定字段:
update t
set x = (case when u.clear_record = 1 or u.x = '99999' then null
when u.x is not null then u.x
else t.x
end),
y = (case when u.clear_record = 1 or u.y = '9999'9 then null
when u.y is not null then u.y
else t.y
end),
z = (case when z.clear_record = 1 or u.z = '99999' then null
when u.z is not null then u.z
else t.z
end)
from @target t join
@updates u
on t.id = u.id;
但是,对于这样一个特殊值,我不会使用
'99999'
。如果值是字符串,我建议使用空字符串('
)或'
或'{null}
我认为您没有处理这个要求:“如果源代码是“99999”,那么将目标字段设置为null。”我不需要清除整个记录,只需要清除特定字段。@TabAlleman。我最初误解了这个要求(因为它适用于整个记录),但我添加了它的逻辑。我认为您没有处理这个要求:“如果源是“99999”,那么将目标字段设置为NULL。”我不需要清除整个记录,只需要清除特定字段。@TabAlleman。我最初误解了这个要求(因为它适用于整个记录),但我为它添加了逻辑。@shorton,如果给定源值,则内部ISNULL
将选择源值,如果源值为null,则选择目标值。因此,如果用户通过99999
,将选择该值。如果两个参数彼此相等,则外部NULLIF
将返回NULL
。因此,当ISNULL
返回99999
时,NULLIF
将返回NULL
。这是一个相当优雅的解决方案+1.@shorton,如果给定源值,则内部ISNULL
将选择源值,如果源值为null,则选择目标值。因此,如果用户通过99999
,将选择该值。如果两个参数彼此相等,则外部NULLIF
将返回NULL
。因此,当ISNULL
返回99999
时,NULLIF
将返回NULL
。这是一个相当优雅的解决方案+谢谢各位。合并对第一部分有效,Tab的建议对第二部分有效。我看不出有什么办法能把你们俩的帮助都归功于我。非常感谢你们,谢谢你们。合并对第一部分有效,Tab的建议对第二部分有效。我看不出有什么办法能把你们俩的帮助都归功于我。非常感谢你们两位。