【问题标题】:SQL Server, can't insert null into primary key field?SQL Server,不能在主键字段中插入空值?
【发布时间】:2011-04-22 01:33:31
【问题描述】:

我正准备在这个上扯掉我的头发。我对 MS SQL 还很陌生,在任何地方都没有看到类似的帖子。

当我尝试做这样的陈述时:

INSERT INTO qcRawMatTestCharacteristic 
VALUES(NULL, 1,1,1,1,1,1,1,'','','', GETDATE(), 1)

我得到以下信息:

无法将值 NULL 插入 列“iRawMatTestCharacteristicId”, 桌子 'Intranet.dbo.qcRawMatTestCharacteristic'; 列不允许空值。插入 失败。

我理解错误,但 null 值适用于我的主字段,其数据类型为 int。

有什么想法吗!?

【问题讨论】:

  • 好的,我应该澄清一下。我只想要一个自动递增的主键。在 MySQL 中,NULL 值会给我这种效果。如果我使用与上面相同的 INSERT 语句,请指定我的字段并省略主键。我得到了同样的错误。
  • @Nick:SQL Server 中的该列必须定义为 INT IDENTITY 才能正常工作。关键是 IDENTITY 部分 - 你需要在你的 PK 列上定义它,否则它将不起作用
  • 我现在明白了,伙计们。非常感谢。我知道关系数据库是如何工作的。但是你回答了我的 MS SQL 问题。 :)
  • @Nick:好的,很高兴我们能提供帮助。 SQL 在一定程度上是标准化的......
  • @Conrad 我知道你在我之前发帖,但我以为你在我之后更新了你的帖子。我看不到时间戳。我只是在开玩笑。

标签: sql sql-server database-design insert


【解决方案1】:

任何关系数据库中的主键不允许为 NULL - 这是主键的主要基本特征之一。

见:SQL by Design: how to Choose the primary key

永不为空
主键值不能为空,也不能做任何事情 使主键为空。 这是 关系的一个不可侵犯的规则 ANSI 支持的模型, 关系数据库管理系统 (RDBMS) 设计,以及 SQL Server。

更新:好的,所以您需要 SQL Server 中的“自动增量”主键。

您需要在 CREATE TABLE 语句中将其定义为 INT IDENTITY:

 CREATE TABLE dbo.YourTable(ID INT IDENTITY, col1 INT, ..., colN INT)

然后当您执行 INSERT 时,您需要明确指定要插入的列,但不要在该列表中指定“ID”列 - 然后 SQL Server 将自动处理查找正确的值:

 INSERT INTO dbo.YourTable(col1, col2, ..., colN) -- anything **except** `ID`      
 VALUES(va1l, val2, ..., valN)

如果您想在已经创建表后执行此操作,您可以在 SQL Server Management Studio 的表设计器中执行此操作:

【讨论】:

  • +1(确定答案)。为了完整起见:unique可以 通常包含 null 值(primary 不能)。
  • @Nick:对 MySQL 感到羞耻!这显然违反了关系模型的 ANSI 规则
  • @Nick & @Marc - 这没有任何意义。如果你真的有一个主键并且 MySQL 允许你插入空值,那么你已经打败了主键的点。这意味着您可以插入具有所有空值的多行,而无法唯一标识每一行。我想知道在 MySQL 中 null 是否会被忽略并且它会自动递增。这就像说你会给两个人相同的身份证号码。你将如何识别他们?
  • 如您的示例所示,始终指定插入列名称是个好主意。
  • @Nelson Rothermal 我不明白为什么您不应该选择将 Null 值作为有效的主键值。 Paradox 允许这样做。主键仍然可以是唯一的 - 您可以拥有 Null 键字段值,但仍然不允许重复键...将 Null 视为另一个值。
【解决方案2】:

MS SQL 中的主键字段不能包含空值。如果您想填充 SQL 表并且不知道为基于整数的主键字段输入什么,则将 pk 设置为 Identity 字段。此外,在指定插入语句时,明智的做法是使用插入语句的列映射部分,例如:

Insert into (field1, field2, field3)
values
(value1, value2, value3)

这样做的原因是它确保列顺序是您开发的目标,因为 SQL 管理员可以修改列顺序。它还允许您插入具有标识主键的行,而无需指定主键示例的值

CREATE TABLE [dbo].[foo](
    [fooid] [int] IDENTITY(1,1) NOT NULL,
    [name] [varchar](50) NULL,
 CONSTRAINT [PK_foo] PRIMARY KEY
(
        [fooid] ASC
)

现在我的插入语句很简单

Insert into foo (name)
values
("John")

表格中的结果是

1, "John"

【讨论】:

    【解决方案3】:

    您可能没有(您忘记添加)整数主键上的自动增量设置。

    【讨论】:

      【解决方案4】:

      主键不应该接受空值。为什么要向主键字段插入空值?主键字段应该有一个不可为空的唯一值,这将使表中的每条记录都是唯一的

      【讨论】:

      • 对于自动增量,即使我将 null 排除在插入参数之外。我得到同样的错误。
      【解决方案5】:

      您只能对 1 个唯一行使用 0 而不是 null,PK 不能使用 null。或者你可以省略PK并使用自动增加PK字段

      【讨论】:

        【解决方案6】:

        假设您的主键有一个自动增量字段,您需要在插入时包含字段列表,而不是为该字段添加值,例如

        INSERT INTO qcRawMatTestCharacteristic 
        (Answer1,Answer2,...SomeDateField)
        VALUES(1,1,1,1,1,1,1,'','','', GETDATE(), 1)
        

        【讨论】:

          【解决方案7】:

          我假设您的真正问题是您不确定如何编写插入语句以便自动填充正确的 PK?您需要命名要为其设置值的字段,看起来您正在尝试设置所有字段,但只排除 PK 字段,如下所示:

          INSERT INTO someTable
          (fieldName1, fieldName2) 
          VALUES(1,1)
          

          其中 sometable 是一个包含三个字段的表。 PK、fieldName1 和 fieldName2。您还需要确保 PK 字段上的标识属性设置为 true。

          【讨论】:

            【解决方案8】:

            如果你有一个标识列,你不需要在插入语句中指定它。

            INSERT INTO qcRawMatTestCharacteristic  
            VALUES(1,1,1,1,1,1,1,'','','', GETDATE(), 1) 
            

            但是,如果您有一个不是标识列的主键,那么您确实需要指定它,否则它会尝试插入空值,并且默认情况下主键不可为空。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-10-11
              • 2018-07-11
              • 1970-01-01
              • 2014-03-26
              • 1970-01-01
              • 1970-01-01
              • 2019-01-24
              • 2019-07-21
              相关资源
              最近更新 更多