【问题标题】:SQL Server insert new rows ONLY based on multiple columnsSQL Server 仅基于多列插入新行
【发布时间】:2016-05-11 04:45:52
【问题描述】:

我在 SO 中进行了搜索,但找不到任何适合我的目的。我只需要将唯一行从一个表插入到另一个表中。我有:

table1

id  name    bookid bookname start_date   end_date   rel_date   rel_id
1   horror  1221   rockys    04/01/2016  04/30/2016 05/01/2016 4545
2   horror  1331   elm       04/01/2016  04/30/2016 05/01/2016 5656

table2

id  name    bookid bookname start_date   end_date   rel_date   rel_id
1   horror  1221   rockys    04/01/2016  04/30/2016 05/01/2016 4545
2   horror  1441   elm       04/01/2016  04/30/2016 05/01/2016 5656

我需要将 table2 中 id = 2 的行插入到 table1 中,并从 table1 中删除 id = 2 的行,因为即使其余列匹配,bookid 也是不同的。 我尝试了以下操作:

insert into table1
select * from table2
where not exists (select * from table2 where table1.id = table2.id
and table1.name = table2.name and table1.bookid = table2.bookid and
table1.bookname = table2.bookname and table1.start_date =  table2.start_date
and table1.end_date = table2.end_date and table1.rel_date =            table2.rel_date
and table1.rel_id = table2.rel_id)

有什么方法可以在一个 sql 块中完成所有这些操作?

【问题讨论】:

  • 使用连接先删除后插入
  • 再想一想,如果只是 bookid 的问题,为什么不能用 join 编写更新查询?
  • 您还可以查看 TSQL 中的MERGE 命令。
  • @techspider -- 在这种情况下,它只是 bookid,它可以是任何/所有剩余的列。我没有识别列,因为这是 ssis 包内的 sql 任务。 - 马特
  • 在您确定两个表中都匹配的标识列之前,您无法正确执行此操作

标签: sql-server tsql


【解决方案1】:

理论上,以下合并语句应该可以实现您所寻找的。

    MERGE table1 [Target]
    USING table2 [Source]
    ON ([Target].[name] = [Source].[name] 
            AND 
        [Target].[bookname] = [Source].[bookname] 
            AND 
        [Target].[start_date] = [Source].[start_date] 
            AND 
        [Target].[end_date] = [Source].[end_date] 
            AND 
        [Target].[rel_date] = [Source].[rel_date] 
            AND 
        [Target].[rel_id] = [Source].[rel_id]  
      )
    WHEN MATCHED AND ([Target].[bookid] <> [Source].[bookid]) THEN
        UPDATE
            SET  [Target].[name]             = [Source].[name]      
                ,[Target].[bookid]           = [Source].[bookid]        
                ,[Target].[bookname]         = [Source].[bookname]  
                ,[Target].[start_date]       = [Source].[start_date]    
                ,[Target].[end_date]         = [Source].[end_date]  
                ,[Target].[rel_date]         = [Source].[rel_date]  
                ,[Target].[rel_id]           = [Source].[rel_id]        
    WHEN NOT MATCHED  THEN
    INSERT(         
             [name]         
            ,[bookid]       
            ,[bookname]     
            ,[start_date]   
            ,[end_date]     
            ,[rel_date]     
            ,[rel_id]       
         )
    VALUES
    (       
             [Source].[name]            
            ,[Source].[bookid]      
            ,[Source].[bookname]        
            ,[Source].[start_date]  
            ,[Source].[end_date]        
            ,[Source].[rel_date]        
            ,[Source].[rel_id]  
    );

请注意,这种方法存在一些风险和限制。如果您的 [id] 列具有唯一性约束,则应将其设置为标识列,否则您将遇到违反唯一性的错误。此外,如果 table1 中的 [id] 列值与 table2 中的 [id] 列不同,则合并语句将保留 table1 中的原始 [id] 值。

基本上,这个查询只是用 table2 中的匹配记录更新 table1 中的现有记录,如果 table2 中的新记录不存在,则将它们插入到 table1 中。

【讨论】:

  • 我没有/不能有任何身份列,因为这是在 ssis 包中的 sql 任务中 ---> 如果我有身份列,该包将无法工作。本质上,我需要的是在任何列/s 不同时进行更新。仅当 start_date 不同时才应进行插入。因此,如果 start_date 相同但任何列不同,则它是一个更新。如果 start_date 不同,那么无论其余列有什么,它都是新行的插入。 - 马特
  • 我明白了,不过我需要更多信息。您要键入哪些列来唯一标识应更新的记录?它是 [id] 列还是其他列的组合,如果是,哪些列?
【解决方案2】:

实现目标所需要做的就是:

UPDATE T1
SET T1.bookid = T2.bookid
FROM Table1 T1
JOIN Table2 T2
    ON T1.ID = T2.ID

但是,要准确回答问题:

DELETE T1
FROM Table1 T1
JOIN Table2 T2
    ON T1.ID = T2.ID
    AND T1.bookid <> T2.bookid

INSERT INTO Table1
SELECT id, name, bookid, bookname, start_date, end_date, rel_date, rel_id
FROM Table2 T2
LEFT OUTER JOIN Table1 T1
    ON T1.ID = T2.ID
    AND T1.bookid = T2.bookid
WHERE T1.id IS NULL

请注意,如果您的 ID 字段不是唯一的,您需要在 ON 子句中添加其他条件。

【讨论】:

    【解决方案3】:

    如果您只是关心从table2 更新bookid 的值,您可以使用以下查询更改bookid 的值

    UPDATE t1 SET t1.bookid = t2.bookid
    FROM table1 t1
    JOIN table2 t2 ON t1.id = t2.id
    

    如果您认为您的id 列在两个表中不是唯一的,您可能需要考虑在JOIN 中添加其他匹配的列。

    【讨论】:

    • 他确实说过“其余列匹配”,因此他的 id 列可能不是唯一的,因此您可能需要在 ON 子句中添加更多内容。
    • 很不确定他真的想用这个例子做什么;但无论如何,我已经添加了你的注释;谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-19
    相关资源
    最近更新 更多