我有2个这样的表:
CREATE TABLE #targetTable(id int,date datetime,name varchar(50));
CREATE TABLE #sourceTable(id int,date datetime,name varchar(50));
INSERT INTO #targetTable values(1,'1905-07-08 00:00:00.000','John');
INSERT INTO #targetTable values(2,'1905-07-08 00:00:00.000','Albrt');
INSERT INTO #targetTable values(3,'1905-07-08 00:00:00.000','Roy');
INSERT INTO #sourceTable values(1,'1905-07-09 00:00:00.000','jame');
我想更新目标表,如果不匹配,则将目标的名称列更新为NULL。我想要这个结果:
id date name
1 1905-07-09 00:00:00.000 jame
2 1905-07-09 00:00:00.000 null
3 1905-07-09 00:00:00.000 null
我的测试查询不起作用:错误:未匹配时不允许进行更新。反正有没有编辑查询以获取结果?
merge into #targetTable a
using #sourceTable b on a.id=b.id
when matched and b.date > a.date then
update
set a.name=b.name,a.date=b.date
when not matched by Target then
update a.date=b.date and a.name = null
它告诉我错误。您能帮我获得结果吗?
答案 0 :(得分:4)
没有冒犯,但您的查询存在很多语法问题。
第二,当不匹配时,merge语句无法更新目标表中的值。您应该尝试插入。
这里是一个示例:
MERGE INTO #targetTable a
USING #sourceTable b
ON a.id=b.id
WHEN MATCHED THEN
UPDATE SET
a.name=b.name,
a.date=b.date
WHEN NOT MATCHED BY TARGET THEN
INSERT
(
id,
date,
name
)
VALUES
(
b.id,
b.date,
null as name
)
答案 1 :(得分:0)
我会使用APPLY
:
UPDATE t
SET t.name = s.name,
t.date = s.date
FROM #targetTable t OUTER APPLY
( SELECT TOP (1) s.*
FROM #sourceTable s
WHERE s.id = t.id
) s;
您的合并也具有Source值:
merge #targetTable a
using #sourceTable b
on a.id=b.id
when matched
then update
set a.name = b.name, a.date= b.date
when not matched by SOURCE
then update
set a.name = null;
答案 2 :(得分:0)
您需要WHEN NOT MATCHED BY SOURCE
,所以像这样:
WHEN NOT MATCHED BY SOURCE
THEN UPDATE
SET a.name = NULL
答案 3 :(得分:0)
因此,如果我遇到问题,您只想在#sourceTable中没有匹配的行时更新表#targetTable中的名称。
您不需要MERGE
语句即可完成此操作。
UPDATE #targetTable
SET
[name] = COALESCE([source].name, NULL)
, date = [source_date].maxDate
FROM
#targetTable AS [target]
LEFT JOIN #sourceTable AS [source] ON [target].id = [source].id
CROSS JOIN (SELECT max(date) AS maxDate FROM #sourcetable) AS [source_date]
WHERE
[source].id IS NULL
这将产生以下输出:
答案 4 :(得分:0)
阅读问题和所有评论后,您真正想要的是
UPDATE
基于id
和date
的行,但是在没有name
的情况下将name
设置为NULL
与此条件匹配并同时将date
设置为最大日期。UPDATE
上存在匹配项时,name
带有新值(date
,id
)为了简单起见,我在这里使用了一个表变量,但是概念是 一样。
给出产生的表和数据:
DECLARE @targetTable TABLE (id int,date datetime,name varchar(50));
DECLARE @sourceTable TABLE (id int,date datetime,name varchar(50));
INSERT INTO @targetTable
VALUES
(1,'1905-07-08 00:00:00.000','John'),
(2,'1905-07-08 00:00:00.000','Albrt'),
(3,'1905-07-08 00:00:00.000','Roy');
INSERT INTO @sourceTable values(1,'1905-07-09 00:00:00.000','jame');
SELECT id,date,name FROM @targetTable;
SELECT id,date,name FROM @sourceTable;
id date name
1 1905-07-08 00:00:00.000 John
2 1905-07-08 00:00:00.000 Albrt
3 1905-07-08 00:00:00.000 Roy
id date name
1 1905-07-09 00:00:00.000 jame
您想要的基本上与此选择语句相同:
SELECT
t.id,
CASE
WHEN s.id IS NOT NULL THEN s.[date]
ELSE (SELECT MAX([date]) FROM @sourceTable )
END AS [date],
CASE
WHEN s.id IS NULL THEN NULL
ELSE s.name
END AS [name]
FROM @targetTable AS t
LEFT OUTER JOIN @sourceTable AS s
ON t.id = s.id;
为此,我们可以将其合并到更新中:
UPDATE @targetTable
SET [date] = CASE
WHEN s.id IS NOT NULL THEN s.[date]
ELSE (SELECT MAX([date]) FROM @sourceTable )
END,
[name] = CASE
WHEN s.id IS NULL THEN NULL
ELSE s.name
END
FROM @targetTable AS t
LEFT OUTER JOIN @sourceTable AS s
ON t.id = s.id;
最终输出
SELECT id,date,name FROM @targetTable;
id date name
1 1905-07-09 00:00:00.000 jame
2 1905-07-09 00:00:00.000 NULL
3 1905-07-09 00:00:00.000 NULL