Reputation: 135
i have 2 Tables like this:
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');
i want to update the Target Table, when not match then update Name Column of Target with NULL. i would like to have this Result:
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
my test Query doesn't work: Error: UPDATE IS NOT ALLOWED IN THE WHEN NOT MATCHED. is there anyway to edit the query to get the Results?
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
it shows me Error. Can you please help me how to get the Result?
Upvotes: 2
Views: 1797
Reputation: 9552
So if I get your problem, you simply want to update the name in table #targetTable if there is no matching row in #sourceTable.
You don't need a MERGE
statement to accomplish this.
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
This yields the following output:
Upvotes: 0
Reputation: 34158
After reading the question and all the comments what you really want is
UPDATE
the row based upon the id
with both the date
and name
but set the name
to NULL
when there is no match and set the date
to the max date at the same time with that condition.UPDATE
with new values (name
,date
) when there is a match on id
I used a table variable for simplicity here but the concept is the same.
Given the table and data this produces:
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
What you desire is basically the same as this select statement:
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;
SO to do that, we can incorporate that into an update:
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;
Final output
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
Upvotes: 0
Reputation: 848
No offense but your query has whole a lot of syntax issues.
Secondly, a merge statement cannot update values in the target table when not matched. You should try inserting instead.
Here is a example:
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
)
Upvotes: 4
Reputation: 3629
You need WHEN NOT MATCHED BY SOURCE
, so something like:
WHEN NOT MATCHED BY SOURCE
THEN UPDATE
SET a.name = NULL
Upvotes: 0
Reputation: 50163
I would use 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;
Your merge has Source value also :
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;
Upvotes: 0