【问题标题】:Prevent duplicate rows being inserted防止插入重复行
【发布时间】:2010-08-02 00:03:54
【问题描述】:

我正在尝试使用 SQL 插入语句将行从一个数据库中的表迁移到另一个数据库中的表。该语句一直有效,直到我在目标表上添加一个唯一索引,此时我正在努力让插入语句能够排除重复项。这是我应该做的:

INSERT INTO [MyDB].[dbo].[HPB] (
    [HPID],
    [BusinessID]
)
SELECT 
    PersonId = (SELECT ID FROM [MyDB].[dbo].[HP] WHERE PersonID = lPersonId),
    lBusinessId
FROM [MyOriginalDB].[dbo].[tblEmployment]
WHERE
    lPersonId in (SELECT PersonID FROM [MyDB].[dbo].[HP])
AND
    lBusinessId in (SELECT ID FROM [MyDB].[dbo].[Business])
AND 
   NOT EXISTS (SELECT * FROM [MyDB].[dbo].[HPB] WHERE 
     [HPID] = (SELECT ID FROM [MyDB].[dbo].[HP] WHERE PersonID = lPersonId) 
     AND [BusinessID] = lBusinessId)

HPB 表的架构是:

CREATE TABLE [dbo].[HPB](
   [ID] [int] IDENTITY(1,1) NOT NULL,
   [HPID] [int] NOT NULL,
   [BusinessID] [int] NOT NULL,
   CONSTRAINT [PK_HealthProfessionalBusiness] PRIMARY KEY CLUSTERED)

唯一索引位于 [MyDB].[dbo].[HPB] 表中的列(HPID、BusinessID)

当我运行插入时,我收到关于重复行插入的错误,我无法弄清楚为什么下面的 SQL 不排除重复项。

 NOT EXISTS (SELECT * FROM [MyDB].[dbo].[HPB] WHERE 
     [HPID] = (SELECT ID FROM [MyDB].[dbo].[HP] WHERE PersonID = lPersonId) 
     AND [BusinessID] = lBusinessId)

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:
    Insert MyDB.dbo.HPB( HPID, BusinessID )  
    Select HP.ID, E.IBusinessID  
    From [MyOriginalDB].[dbo].[tblEmployment] As E
        Join [MyDB].[dbo].[HP] As HP
            On HP.PersonId = E.IPersonID
        Join [MyDB].[dbo].[Business] As B
            On B.ID = E.IBusinessID
        Left Join [MyDB].[dbo].[HPB] As HPB
            On HPB.BusinessID = E.IBusinessID
                And HPB.PersonID = E.IPersonId
    Where HPB.ID Is Null
    Group By HP.ID, E.IBusinessID
    

    【讨论】:

    • 请注意,LEFT JOIN/IS NULL 仅在 MySQL 上更快 - 在 SQL Server 上,NOT IN 和 NOT EXISTS 更有效:explainextended.com/2009/09/15/…
    • @OMG Ponies - 我不知道 Left Join 与 Exists 的性能差异。我想我一直有测试每个执行计划的习惯,以查看哪个更有效。当然,这会推动我的记忆,但我似乎记得在 SQL Server 上的某些情况,其中 Left Join 和 null 比 Exists 和其他情况相反的情况更快。或许,这只是感知。
    • @Thomas:谢谢,根据您的陈述,我几乎可以正常工作了。我需要将 tblEmployment 中的另一列添加到插入和选择中,但是一旦我这样做,它就会通过强制唯一性的机制破坏组。
    • @sipwiz - 您需要将该附加列放在聚合函数中。所以像Min(E.OtherCol)Max(E.OtherCol)
    【解决方案2】:

    用途:

    INSERT INTO [MyDB].[dbo].[HPB] 
      ([HPID], [BusinessID])
    SELECT DISTINCT
           h.id,
           e.lbusinessid
      FROM [MyOriginalDB].[dbo].[tblEmployment] e
      JOIN [MyDB].[dbo].[HP] h ON h.personid = e.lpersonid
     WHERE e.lbusinessid in (SELECT ID FROM [MyDB].[dbo].[Business])
       AND NOT EXISTS (SELECT NULL 
                         FROM [MyDB].[dbo].[HPB] hb
                        WHERE hb.businessid = e.lbusinessid
                          AND hb.hpid = h.id)
    

    【讨论】:

    • DISTINCT 关键字是我所需要的,因为 NOT EXISTS 子句不会阻止新行及其重复项都被添加到同一批次中。
    猜你喜欢
    • 2015-08-07
    • 2016-02-19
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2018-04-11
    • 1970-01-01
    相关资源
    最近更新 更多