【问题标题】:how to avoid inserting duplicates on a key-less table?如何避免在无键表上插入重复项?
【发布时间】:2018-06-19 15:35:17
【问题描述】:

我被要求将以下代码转换为 merge。以前一个月运行一次,现在应该每天运行一次……

在以下之前,EmailEvent 被截断:

DECLARE @upperLimit DATETIME = GETDATE();
DECLARE @lowerLimit DATETIME = DATEADD(day,-1,@upperLimit);

WHILE @upperLimit > '2013-01-31 10:03:09.000'
BEGIN
 INSERT INTO EmailEvent
 Select l.SalesForceID, 
       DENSE_RANK ( ) OVER (PARTITION BY es.email order by sentdate) as [EmailCount],
       es.SentDate,
       esd.eventtype,
       esd.eventdate

 FROM EmailSentDetails esd
 join Silverpop_EmailSent es on esd.emailsent_id = es.EmailSent_ID
 join Leads l on l.Email = es.Email

 WHERE es.SentDate <= @upperLimit AND es.SentDate >= @lowerLimit 


 SET @upperLimit = @lowerLimit;
 SET @lowerLimit = DATEADD(day,-1, @lowerLimit);

END

我知道 MERGE 无法完成,因为 EmailEvent 上没有键(无法唯一标识一行!)

我唯一能想到的是,不是截断/插入,而是添加以下内容,它会改善它吗?这是避免截断/插入的有效方法吗?

WHERE Not exists (select 1 from EmailEvent ev 
                  where ev.salsforceId=l.SalesForceID 
                  and ev.emailcount = DENSE_RANK ()OVER(PARTITION BY es.email order by sentdate) 
                  and ev.sentDate=es.SentDate 
                  and ev.EventDate=esd.EventDate)

【问题讨论】:

  • 添加主键怎么样?
  • 由于某种原因不能添加密钥吗?
  • 我有点迷失为什么你甚至循环而不是更大的插入......看起来你可以创建一个子查询来获取你的数据,然后只做一个更大的插入,但我在这里可能非常错误......
  • 即使我加了,源码也没有一键。
  • 为什么那个时间在上限?为什么不只是白天。

标签: sql sql-server tsql merge


【解决方案1】:

您可以对表中的所有列执行 MERGE。

但这太过分了,因为您永远不会对 MERGE 进行任何更新。

您真正需要做的只是一个 INSERT .. WHERE NOT EXISTS() 来检查表中的所有列,正如您在问题中所建议的那样。我就是这样做的。

【讨论】:

    【解决方案2】:

    在要避免重复的列上放置唯一索引并使用 IGNORE_DUP_KEY。这会忽略添加重复项的尝试,允许插入继续:

    CREATE UNIQUE NONCLUSTERED INDEX [IX_AvoidDuplicateEntries] ON [dbo].[MyTable]
    (
        [MyColumn1] ASC --, [MyColumn2] ASC, [MyColumn3] ASC etc.
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = ON, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    

    【讨论】:

    • uniquness 来自SalesforceId、EmailCount、SentDate、EventType、EventDate,所以基本上是整个表,我应该这样添加吗?
    • @Chicago1988 它浪费磁盘空间和性能,但也许你没有选择?您可以按任何顺序排列列,但至少可以添加以便查询会发现它有用。
    • 创建唯一索引实际上是愚蠢的,因为它会消耗大量资源(CPU/存储)只是为了避免重复,UNIQUE CONSTRAINT 正是为此而存在的。
    • @ThomasG 你确定它们不一样吗?
    • @ThomasG 尝试停止插入重复项。如果尝试重复,唯一约束将停止所有插入,但我的建议只是忽略重复。我解释说这很浪费,但确实解决了问题;只是解释了所有列的唯一性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多