没有匹配项时如何更新row = NULL

时间:2019-04-05 11:07:51

标签: sql sql-server

我有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 

它告诉我错误。您能帮我获得结果吗?

5 个答案:

答案 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

这将产生以下输出:

enter image description here

答案 4 :(得分:0)

阅读问题和所有评论后,您真正想要的是

  • UPDATE基于iddate的行,但是在没有name的情况下将name设置为NULL与此条件匹配并同时将date设置为最大日期。
  • UPDATE上存在匹配项时,
  • name带有新值(dateid

为了简单起见,我在这里使用了一个表变量,但是概念是    一样。

给出产生的表和数据:

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