【问题标题】:Violation of PRIMARY KEY constraint 'xx'. Cannot insert duplicate key in object 'cc'. The duplicate key is (x)违反 PRIMARY KEY 约束“xx”。无法在对象“cc”中插入重复键。重复键是 (x)
【发布时间】:2020-07-17 21:57:24
【问题描述】:

为了更好地理解而更新了问题,因为我找到了解决方案,所以我一直在寻找:

我的脚本是这样的:

CREATE TABLE [dbo].[MyTable]
(
    [Columndata1] [nvarchar] (255) NOT NULL,
    [Columndata2] [nvarchar] (max) NOT NULL,
    [Columndata3] [nvarchar] (max) NOT NULL,
    [ColumndataTime] [datetime] NOT NULL,

    CONSTRAINT [PK_MyTable] 
        PRIMARY KEY CLUSTERED ([Columndata1] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[MyTable] 
    ADD CONSTRAINT [DF_MyTable_ColumndataTime] DEFAULT (getutcdate()) FOR [ColumndataTime]
GO

我正在尝试解决重复 PK 的情况,这样如果发生这种情况,它应该忽略请求,如果不创建表。

我想我在最初的问题中并不清楚。

【问题讨论】:

  • dbo 通常是 ms sql server 架构而不是 mysql 架构,你确定你有 m,ysql 吗?
  • 该错误仅表示您的插入或更新语句在Columndata1 列中创建了重复值。没有比这更复杂的了。
  • 不要插入重复记录。您正在插入或更新记录,以便出现重复项。 PK 存在的一个原因是停止插入重复项,并且您专门创建了一个。
  • 你为什么要在Columndata1上创建一个PK?听起来您可能正在边做边学,这非常好,比这里的很多帖子要好得多。要停止直接问题,请从表中删除 PK。然后想一想:您的数据中是否有任何东西可以唯一标识每一行?如果不是,通常的解决方案是创建一个 INT IDENTITY 列来为您完成。
  • Columndata1中的值是怎么产生的?除非你有特定的逻辑来确保它是独一无二的,否则没有理由认为它是独一无二的

标签: sql sql-server database duplicates


【解决方案1】:

我认为您已经有了答案,您正在向指定为主键的列插入重复值,您收到的错误告诉您这一点,这一切都特别清楚。我可以看出您假设正在发生更“险恶”的事情,但似乎情况并非如此,这不是“竞争条件”或更复杂的事情。

但是,我认为可能值得指出一些我认为有点“危险信号”的东西。也许这不能归类为答案,但它确实解决了您原始问题中的一些问题,特别是当您开始询问 CREATE TABLE 脚本的“复杂”部分中的选项时,评论太长了?

如果您有一个“默认”开箱即用的 SQL Server 安装,那么您的 CREATE TABLE 脚本中 90% 的语句都是多余的默认设置。

我可以运行这个脚本:

CREATE TABLE [dbo].[MyTable] (
    [Columndata1] [nvarchar] (255) NOT NULL,
    [Columndata2] [nvarchar] (max) NOT NULL,
    [Columndata3] [nvarchar] (max) NOT NULL,
    [ColumndataTime] [datetime] NOT NULL,
    CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED ([Columndata1]));

然后我可以直接从 SSMS 生成表的创建脚本来获取:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable](
    [Columndata1] [nvarchar](255) NOT NULL,
    [Columndata2] [nvarchar](max) NOT NULL,
    [Columndata3] [nvarchar](max) NOT NULL,
    [ColumndataTime] [datetime] NOT NULL,
 CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED 
(
    [Columndata1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

第二个脚本现在看起来与您帖子中的脚本非常相似,不是吗?

现在指定所有这些默认选项并没有什么问题,在某些情况下它可能最终对您有利,但我个人的偏好(以及与我共事过的每个人的偏好)是省略默认选项选项,因为它们只会使脚本更难同行评审,并且本质上是“混乱”的。您可以争论是否值得在PRIMARY KEY 部分中指定ASC,其中一些是假设的知识,并且微软总是有可能决定在未来更改默认值(然后第一个脚本将'不产生你想要的)。然而,从务实的角度来看这些事情是如何运作的,微软在未来版本中改变这些选项的机会非常渺茫,因为它会破坏这么多在野外使用的数据库。

随心所欲,但我认为值得尝试解释一下,因为您似乎对原文中的“长部分”(您的话)有点着迷(可能是错误的词:))查询?

【讨论】:

  • 重读这篇文章,它比我预想的更“刻薄”,所以对此表示歉意,4 月 6 日对我来说一定是艰难的一天 :)
  • 不,它很完美,转移了我的注意力,最终找到了正确的答案。谢谢。
【解决方案2】:

我的解决方案是在 SQL 中使用 WHERE NOT EXISTS 语句,这极大地启发了这个答案:https://stackoverflow.com/a/3025332

INSERT INTO `table` (`value1`, `value2`) 
SELECT 'stuff for value1', 'stuff for value2' FROM DUAL 
WHERE NOT EXISTS (SELECT * FROM `table` 
      WHERE `value1`='stuff for value1' AND `value2`='stuff for value2' LIMIT 1) 

这样我就不会重复了。

感谢 Richard Hansell 的解释,让我将注意力从“复杂”部分转移。

【讨论】:

    猜你喜欢
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    相关资源
    最近更新 更多