【问题标题】:insert ignoring duplicates using TSQL使用 SQL 插入忽略重复项
【发布时间】:2013-05-15 07:07:43
【问题描述】:

我有一个对 2 列具有唯一约束的表:

CREATE TABLE MIGRATION_DICTIONARIES.dbo._TableQueue_ (
    Id INT IDENTITY PRIMARY KEY,
    TableName VARCHAR(250),
    TableFrom VARCHAR(250),
    KeyName VARCHAR(250),
    Processed INT DEFAULT 0,

    CONSTRAINT [UQ_codes] UNIQUE NONCLUSTERED
    (
        TableName, TableFrom
    )
)

在我尝试实现的过程中,我需要使用 INSERT INTO (...) SELECT 插入一堆记录。现在,如何确保忽略与约束重复的所有行,但仍保存 select 语句给出的所有其他行?

插入查询:

INSERT INTO MIGRATION_DICTIONARIES.dbo._TableQueue_ (TableName, TableFrom, KeyName)
SELECT 'some_table_name', t.name as TableWithForeignKey, c.name as ForeignKeyColumn 
from sys.foreign_key_columns as fk
inner join sys.tables as t on fk.parent_object_id = t.object_id
inner join sys.columns as c on fk.parent_object_id = c.object_id and fk.parent_column_id = c.column_id
where fk.referenced_object_id = (select object_id from sys.tables where name = 'some_table_name')

[编辑] 我以以下查询结束:

MERGE MIGRATION_DICTIONARIES.dbo._TableQueue_ AS T
USING (
    SELECT 'SomeTable' as TableFrom, t.name as TableWithForeignKey, c.name as ForeignKeyColumn 
    from sys.foreign_key_columns as fk
    inner join sys.tables as t on fk.parent_object_id = t.object_id
    inner join sys.columns as c on fk.parent_object_id = c.object_id and fk.parent_column_id = c.column_id
    where fk.referenced_object_id = (select object_id from sys.tables where name = 'SomeTable')
) AS S
ON (T.TableName = S.TableWithForeignKey AND T.TableFrom = S.TableFrom)
WHEN NOT MATCHED BY TARGET THEN
    INSERT (TableName, TableFrom, KeyName)
    VALUES (S.TableFrom, S.TableWithForeignKey, S.ForeignKeyColumn);

但是当我运行它时,我仍然得到约束错误:

Violation of UNIQUE KEY constraint 'UQ_codes'. Cannot insert duplicate key in object 'dbo._TableQueue_'. The duplicate key value is (UP_Opiekun, UP_Uczen).
The statement has been terminated.

我做错了什么?

【问题讨论】:

  • 请问什么版本的 SQL Server?

标签: tsql stored-procedures constraints


【解决方案1】:

对于 SQL Server 2008,您可以使用带有“WHEN NOT MATCHED BY TARGET”子句的 MERGE 语句来插入。不要使用“WHEN MATCHED”子句

更一般的,你也可以使用

INSERT dbo._TableQueue_
   (....)
SELECT
   ...
FROM
   SOurce S
WHERE
   NOT EXISTS (SELECT *
      FROM dbo._TableQueue_ T
      WHERE
         S.TableName = T.TableName AND S.TableFrom = T.TableFrom
      )

评论后:

MERGE INTO dbo._TableQueue_ T
USING Source S
       ON S.TableName = T.TableName AND S.TableFrom = T.TableFrom
WHEN NOT MATCHED BY TARGET THEN
   INSERT (...)
   VALUES (S.x. S.y, ...);

【讨论】:

  • 它将在 2012 年运行,因此匹配的解决方案可能很有用。但是,我应该如何使用 merge 代替 insert into select 语句?你能举个例子吗?
  • 嗯,当你有一个具体的源作为表时似乎很容易,但是更复杂的查询呢?我添加了需要在主帖中使用的插入查询。
  • 查看 MSDN 示例。您只需按照我的链接中的示例 A 将源查询放在 ( ) 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2020-01-03
  • 2023-03-13
  • 2011-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多