【问题标题】:Cannot insert duplicate key error message for update query无法为更新查询插入重复键错误消息
【发布时间】:2019-07-03 14:47:06
【问题描述】:

我正在尝试使用此更新查询更新数据....不插入。但我收到此错误消息。如何解决这个问题

消息 2627,级别 14,状态 1,程序 BF_TR_BUDCONTRACTS_HISTORY_INSERTUPDATE,第 67 行违反 UNIQUE 关键约束“UK_BudContractHis”。无法插入重复键 对象“dbo.BUDCONTRACTS_HISTORY”。重复键值为 (10567, 4377、228、1)。声明已终止。

Update BUDCONTRACTS
 set    BUDCONTRACTS.VERSIONID = 1
       ,BUDCONTRACTS.STATUSID = 1
       ,BUDCONTRACTS.ImportedRecord = 1
       ,BUDCONTRACTS.CUSTOMERID = BCUST.CustomerID
       ,BUDCONTRACTS.LastModifiedUserID = 'Import'
       ,BUDCONTRACTS.LASTMODIFIEDDATETIME = GETDATE()
FROM BUDCONTRACTS BCON
INNER JOIN External_Blk_Itm_Contracts EBIC WITH(NOLOCK) ON BCON.ContractName = EBIC.ContractName  AND EBIC.ContractName = '00-000'
INNER JOIN BUDTERMINALS BT WITH(NOLOCK) ON BT.MBFTERMINALNAME = EBIC.TerminalName AND BT.TERMINALID = BCON.TERMINALID
INNER JOIN BudCustomers BCUST WITH(NOLOCK) ON BCUST.LegalName = EBIC.CustomerName AND BCUST.CustomerID = BCON.CUSTOMERID 
AND (
   (BCON.STATUSID <> 1) 
OR (BCON.ImportedRecord <> 1) 
OR (ISNULL(BCON.CUSTOMERID,'') <> ISNULL(BCUST.CustomerID,'')
))

【问题讨论】:

  • 您可能正在尝试将其中一个键列更新为表中已存在的值。
  • 更新命令中不涉及表 BUDCONTRACTS_HISTORY。这是完整的程序代码吗?表 BUDCONTRACTS 是否有任何触发器?
  • customerid 列存在 unqiue 键约束
  • 再次使用 NOLOCK 提示更新?这只是这里的主要问题之一。您正在使用更新,但您正在更新表。您需要更新别名,因为有时它会出错并更新不正确的行。您也不应该在集合谓词列表中使用表名或别名,因为无论如何您一次只能更新一个表。为了您的数据,请您的公司和您的系统从您的查询中获取这些 NOLOCK。它们有目的,但一直使用它们是一场噩梦。
  • @SeanLange,您能否发布一个示例来纠正我的上述查询,以便我可以在以后的查询中遵循相同的模式

标签: sql-server


【解决方案1】:

我遇到了同样的问题,结果我在更新语句中没有足够的键来仅更新 1 条记录,当我运行它返回超过 1 行的查询并且更新失败时。这很好,因为我已经更改了额外字段的聚集索引。

【讨论】:

    【解决方案2】:

    这是编写此更新的更好方法。

    Update BCON
    set VERSIONID = 1
        , STATUSID = 1
        , ImportedRecord = 1
        , CUSTOMERID = BCUST.CustomerID
        , LastModifiedUserID = 'Import'
        , LASTMODIFIEDDATETIME = GETDATE()
    FROM BUDCONTRACTS BCON
    INNER JOIN External_Blk_Itm_Contracts EBIC ON BCON.ContractName = EBIC.ContractName  AND EBIC.ContractName = '00-000'
    INNER JOIN BUDTERMINALS BT ON BT.MBFTERMINALNAME = EBIC.TerminalName AND BT.TERMINALID = BCON.TERMINALID
    INNER JOIN BudCustomers BCUST ON BCUST.LegalName = EBIC.CustomerName AND BCUST.CustomerID = BCON.CUSTOMERID 
    AND 
    (
        BCON.STATUSID <> 1
        OR
        BCON.ImportedRecord <> 1
    ) 
    --OR ISNULL(BCON.CUSTOMERID,'') <> ISNULL(BCUST.CustomerID,'' This is pointless here because you already joined where these values are equal
    

    现在讨论实际问题。您没有在此查询中引用 dbo.BUDCONTRACTS_HISTORY,因此很明显 BUDCONTACTS 上有一个 UPDATE 触发器。这就是问题所在。它可能试图在历史表中插入一行,但已经有一行具有键值,因此无法插入该行。如果您可以发布 dbo.BUDCONTRACTS_HISTORY 的触发器代码和表定义,我们可以帮助您理顺触发器。

    【讨论】:

    • 谢谢@Sean Lange 明白了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 2013-08-02
    相关资源
    最近更新 更多