【问题标题】:Cannot insert explicit value for identity column in table 'table' when IDENTITY_INSERT is set to OFF当 IDENTITY_INSERT 设置为 OFF 时,无法在表“表”中插入标识列的显式值
【发布时间】:2010-11-22 23:17:49
【问题描述】:

执行以下脚本时出现以下错误。错误是什么,如何解决?

Insert table(OperationID,OpDescription,FilterID)
values (20,'Hierachy Update',1)

错误:

服务器:消息 544,级别 16,状态 1,第 1 行

当 IDENTITY_INSERT 设置为 OFF 时,无法为表“table”中的标识列插入显式值。

【问题讨论】:

  • @HimanshuAhuja 这个问题 (1334012) 已有 10 年历史,您只链接了 1 个问题。如果有的话,那么较新的问题是重复的。但仔细观察你会发现它们不同(较新的将 IDENTITY_INSERT 指定为 ON)。请删除您的标记/评论。
  • @jasie 会这样做,因为我不记得我何时发布此标志

标签: sql sql-server sybase


【解决方案1】:

您正在为OperationId 插入值,这是一个身份列。

您可以像这样在表上打开标识插入,以便您可以指定自己的标识值。

SET IDENTITY_INSERT Table1 ON

INSERT INTO Table1
/*Note the column list is REQUIRED here, not optional*/
            (OperationID,
             OpDescription,
             FilterID)
VALUES      (20,
             'Hierachy Update',
             1)

SET IDENTITY_INSERT Table1 OFF 

【讨论】:

  • +1 准确 - 打开选项以允许显式插入 ON,然后插入,然后再次打开选项 OFF
  • 如果您真的想将您的值添加到标识列,这是您的答案,但另一方面,有人已将列设置为在插入时自行递增。在这种情况下,该表将跟踪下一个空闲号码,您无需自己生成 OperationID。新的 id 可以通过 SELECT SCOPE_IDENTITY() 获取。
  • 很好的答案,但请确保您知道自己在做什么。对我来说,使用需要在不同表上匹配外键的数据为数据库播种是很有用的
  • @marc_s 为什么要再次关闭它?不能只设置ON,这样我们每次需要在表上插入记录时就不需要设置ON/OFF了吗?
  • @UlyssesAlves:此选项只能为数据库范围内的单个表打开 - 因此,如果您为一个表保留它,您将无法曾经将它用于另一张桌子。另外:这不是一个应该保留的选项 - 默认情况下,您应该让 SQL Server 处理标识值 - 这旨在作为非常特定情况下的最后手段 - 不是通用的选择在你的空闲时间离开或离开......
【解决方案2】:

不要为 OperationID 赋值,因为它会自动生成。试试这个:

Insert table(OpDescription,FilterID) values ('Hierachy Update',1)

【讨论】:

  • 如果您想自动生成 OperationID,这是正确的答案
【解决方案3】:

如果您在 SQL Server 上遇到此错误,请运行此查询-

SET IDENTITY_INSERT tableName ON

这仅适用于单个数据库表 例如,如果表名是 student,则查询如下所示:

SET IDENTITY_INSERT student ON

如果您在 Web 应用程序或使用实体框架时遇到此错误,则首先在 SQL 服务器上运行此查询并更新您的实体模型 (.edmx file) 并构建您的项目 这个错误会得到解决

【讨论】:

  • 在我的带有 EF 的 MVC Web 应用程序中就是这种情况,我刚刚从 .edmx 中删除了模型并重新添加(右键单击从数据库中更新模型)并清理并重建项目,然后该项目适用我。谢谢@Umang Patwa
【解决方案4】:

在将 IDENTITY_INSERT 设置为 ON 时要非常小心。除非数据库处于维护模式并设置为单用户,否则这是一种不好的做法。这不仅会影响您的插入,还会影响其他任何试图访问该表的人。

您为什么要尝试将值放入标识字段?

【讨论】:

  • 以什么方式影响?这是一个会话级别的选项,不是表的属性。
  • 在您想要维护关系的两个数据库之间进行一次数据同步。例如,我用它将我的产品架构从一个数据库拉到另一个数据库
  • @NSjonas,这将是一个很好的使用 set Identity _insert table1 ON。我见过有人想用它在应用程序中做一些事情,这些事情应该通过简单的插入来完成,并允许生成身份。
  • 问题是“你能指定它是什么以及如何解决它吗?”您的回答是引发警告和另一个问题的评论,而不是解决问题的正确答案。
  • 是的,不要在主键中插入值。
【解决方案5】:

在该表的实体中,在设置了标识插入的列上方添加DatabaseGenerated 属性:

例子:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TaskId { get; set; }

【讨论】:

  • 嗯,没错,但我真的很想知道 EF 的答案 :-) 不过,这对于可能从未使用过,甚至可能从未遇到过 EF 的 OP 来说并不合适。
  • 无论如何,答案是错误的。我的实体已经用DatabaseGeneratedOption.Identity 指定,但我仍然收到错误消息。这是我自己的错,我将伪 ID 放在新行中以在我的网页上将它们彼此区分开来,我希望在 insert 之前将它们清空就足够了。
【解决方案6】:

基本上有两种不同的方式来插入记录而不会出错:

1) 当 IDENTITY_INSERT 设置为 OFF 时。主键“ID”不得存在

2) 当 IDENTITY_INSERT 设置为 ON 时。主键“ID”必须存在

根据以下示例,使用 IDENTITY PRIMARY KEY 创建的同一表:

CREATE TABLE [dbo].[Persons] (    
    ID INT IDENTITY(1,1) PRIMARY KEY,
    LastName VARCHAR(40) NOT NULL,
    FirstName VARCHAR(40)
);

1) 在第一个示例中,当 IDENTITY_INSERT 为 OFF 时,您可以向表中插入新记录而不会出错。 “INSERT INTO”语句中的主键“ID”不得存在,并且将自动添加唯一的 ID 值:。如果在这种情况下,INSERT 中存在 ID,您将收到错误“无法为表中的标识列插入显式值...”

SET IDENTITY_INSERT [dbo].[Persons] OFF;
INSERT INTO [dbo].[Persons] (FirstName,LastName)
VALUES ('JANE','DOE'); 
INSERT INTO Persons (FirstName,LastName) 
VALUES ('JOE','BROWN');

TABLE [dbo].[Persons] 的输出将是:

ID    LastName   FirstName
1     DOE        Jane
2     BROWN      JOE

2) 在第二个示例中,您可以在 IDENTITY_INSERT 为 ON 时向表中插入新记录而不会出错。 “INSERT INTO”语句中的主键 “ID”必须存在只要 ID 值不存在:如果 ID 不存在于 INSERT在这种情况下,您将收到错误“必须为标识列表指定显式值...”

SET IDENTITY_INSERT [dbo].[Persons] ON;
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (5,'JOHN','WHITE'); 
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (3,'JACK','BLACK'); 

TABLE [dbo].[Persons] 的输出将是:

ID    LastName   FirstName
1     DOE        Jane
2     BROWN      JOE
3     BLACK      JACK
5     WHITE      JOHN

【讨论】:

  • 另外一个用于实际解释标志的工作原理。拯救了我的一天超人
【解决方案7】:

例如,如果您的表名是 School,您可以简单地使用此语句。 在插入之前确保 identity_insert 设置为 ON 并在插入查询之后将 identity_insert OFF

SET IDENTITY_INSERT School ON
/*
  insert query
  enter code here
*/
SET IDENTITY_INSERT School OFF

【讨论】:

  • 您能否稍微扩展您的答案,包括对该命令的解释、它为什么起作用以及它有什么作用?
  • @gareththegeek 是的,对于身份列,您必须确保插入数据。
【解决方案8】:

请注意,如果您用; 关闭每一行,则SET IDENTITY_INSERT mytable ON 命令将不适用于以下行。


这样的查询
SET IDENTITY_INSERT mytable ON;
INSERT INTO mytable (VoucherID, name) VALUES (1, 'Cole');

给出错误
Cannot insert explicit value for identity column in table 'mytable' when IDENTITY_INSERT is set to OFF.

但是这样的查询会起作用:

SET IDENTITY_INSERT mytable ON
INSERT INTO mytable (VoucherID, name) VALUES (1, 'Cole')
SET IDENTITY_INSERT mytable OFF;

似乎SET IDENTITY_INSERT 命令只对事务有效,而; 将表示事务结束。

【讨论】:

    【解决方案9】:

    如果您使用 liquibase 更新您的 SQL Server,您可能会尝试将记录键插入到 autoIncrement 字段中。通过从插入中删除列,您的脚本应该运行。

    <changeSet id="CREATE_GROUP_TABLE" >
        <createTable tableName="GROUP_D">
            <column name="GROUP_ID" type="INTEGER" autoIncrement="true">
                <constraints primaryKey="true"/>
            </column>
        </createTable>
    </changeSet>
    
    <changeSet id="INSERT_UNKNOWN_GROUP" >
        <insert tableName="GROUP_D">    
    
            <column name="GROUP_ID" valueNumeric="-1"/>
     ...
        </insert>
    </changeSet>
    

    【讨论】:

      【解决方案10】:

      每个人都对 SQL 发表评论,但在 EntityFramework 中发生了什么?我花了整篇文章阅读,没有人解决 EF。所以几天后找到了解决方案: EF Core 在创建模型的上下文中有这样一条指令: modelBuilder.Entity&lt;Cliente&gt;(entity =&gt; { entity.Property(e =&gt; e.Id).ValueGeneratedNever();

      这也会产生错误,解决方案:您必须通过 ValueGeneratedOnAdd() 及其工作进行更改!

      【讨论】:

        【解决方案11】:

        您的查询中有预先提到的 OperationId,它不应该存在,因为它是自动递增的

        Insert table(OperationID,OpDescription,FilterID)
        values (20,'Hierachy Update',1)
        

        所以你的查询将是

        Insert table(OpDescription,FilterID)
        values ('Hierachy Update',1)
        

        【讨论】:

          【解决方案12】:

          另一种情况是检查主键是否与您的类同名,唯一的区别是您的主键附加了一个“ID”或指定 [Key]在与类的命名方式无关的主键上。

          【讨论】:

            【解决方案13】:
            1. 当您有一个(主键)列在 SQL 中未将 Is Identity 设置为 true 并且您在插入期间未传递其显式值时,就会发生这种情况。它将占用第一行,然后您将无法插入第二行,将弹出错误。这可以通过在 PrimaryKey 列中添加这行代码 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 来纠正,并确保将其设置为数据类型 int。如果该列是主键并且在 SQL 中将 IsIDentity 设置为 true,则不需要这行代码[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

            【讨论】:

            • 感谢这是我花了几个小时寻找的修复方法。
            【解决方案14】:

            最好的办法是使用注解GeneratedValue(strategy = ...),即

            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            @Column ...
            private int OperationID;
            

            它说,这个列是由数据库使用 IDENTITY 策略生成的,你不需要照顾 - 数据库会做的。

            【讨论】:

              【解决方案15】:

              如果您在使用带有 sequelize-typescript npm 的 sql-server 时遇到此问题,请确保将 @AutoIncrement 添加到 ID 列:

                @PrimaryKey
                @AutoIncrement
                @Column
                id!: number;
              

              【讨论】:

                【解决方案16】:

                在我的例子中,我在我的模型构建器的上下文中设置了另一个属性作为键。

                modelBuilder.Entity<MyTable>().HasKey(t => t.OtherProp);
                

                我必须设置正确的 id

                 modelBuilder.Entity<MyTable>().HasKey(t => t.Id);
                

                【讨论】:

                  【解决方案17】:

                  EF Core 3.x

                  参考Leniel Maccaferri,我有一个表,其中有一个名为 ID(原始主键)的自动增量属性和另一个名为 Other_ID(新主键)的属性。最初 ID 是主键,但后来 Other_ID 需要成为新的主键。由于 ID 正在应用程序的其他部分中使用,因此我不能只将其从表中删除。 Leniel Maccaferri 解决方案仅在我添加以下 sn-p 后对我有效:

                          entity.HasKey(x => x.Other_ID);
                          entity.Property(x => x.ID).ValueGeneratedOnAdd();
                  

                  下面的完整代码 sn-p (ApplicationDbContext.cs):

                    protected override void OnModelCreating(ModelBuilder builder)
                    {
                          builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
                          base.OnModelCreating(builder);
                          builder.Entity<tablename>(entity =>
                          {
                              entity.HasKey(x => x.Other_ID);
                              entity.Property(x => x.ID).ValueGeneratedOnAdd();
                              entity.HasAlternateKey(x => new { x.Other_ID, x.ID });                
                          });
                          
                      }
                  

                  【讨论】:

                  • 我的桌子和你的一模一样,卡住的是旧的Id。要修复它,只需将旧的ID 保留为零0,DB 将确定是否泛化一个新的 id,并且可以在不添加 AlternateKey 的情况下修复错误
                  【解决方案18】:
                  1. 首先转到所需的表名

                  步骤 2 -> 右键单击​​表名

                  第 3 步 --> 选择设计

                  第四步 --> 点击列名

                  第 5 步)转到列属性,然后将 No 设置为 Identity Specification

                  [注意:在插入显式值后,如果您愿意,您可以恢复身份规范,然后再次生成值]

                  如果您使用 SQL Server Management Studio,您可以使用以下方法

                  步骤 1) 第2步)

                  【讨论】:

                    【解决方案19】:

                    如果你使用Oracle SQL Developer连接,记得添加/sqldev:stmt/

                    /sqldev:stmt/set identity_insert TABLE on;

                    【讨论】:

                    • 显然不是这样,问题有一个“sql-server”标签
                    【解决方案20】:

                    我不确定“插入表”的用途是什么,但如果您只是想插入一些值,请尝试:

                    Insert Into [tablename] (OpDescription,FilterID)
                    values ('Hierachy Update',1);
                    

                    我收到了同样的错误消息,但我认为这应该可行。只要是主键,ID 就应该自动递增。

                    【讨论】:

                      【解决方案21】:

                      每次我想向数据库中添加任何内容时,我都会通过创建一个新对象来解决这个问题。

                      【讨论】:

                        【解决方案22】:

                        在我的案例中,我插入的字符比表中定义的要多。

                        在我的表格列中定义了nvarchar(3),我传递了超过 3 个字符,同样的ERROR 消息即将到来。

                        它不是答案,但在某些情况下可能是类似的问题

                        【讨论】:

                          【解决方案23】:

                          我正在使用 asp.net core 5.0,我得到了那个错误。我收到该错误是因为我正在添加另一个数据并触发另一个 .SaveChanges() 方法,如下所示:

                           _unitOfWorkVval.RepositoryVariantValue.Create(variantValue);
                           int request = HttpContext.Response.StatusCode;
                           if (request == 200)
                           {
                               int tryCatch = _unitOfWorkCVar.Complete();
                               if (tryCatch != 0)
                               {
                                   productVariant.CategoryVariantID = variantValue.CategoryVariantID;
                                   productVariant.ProductID = variantValue.ProductID;
                                   productVariant.CreatedDate = DateTime.Now;
                                   _unitOfWorkProductVariant.RepositoryProductVariant.Create(productVariant);
                                   _unitOfWorkVval.RepositoryVariantValue.Create(variantValue);
                                   int request2 = HttpContext.Response.StatusCode;
                                   if(request==200)
                                   {
                                       int tryCatch2=_unitOfWorkProductVariant.Complete();//The point where i get that error
                                   }///.......
                          
                          

                          【讨论】:

                            【解决方案24】:

                            在使用带有这样的模型的实体框架时遇到了同样的问题(我简化了原始代码):

                            public class Pipeline
                            {
                              public Pipeline()
                              {
                                 Runs = new HashSet<Run>();
                              }
                            
                              public int Id {get; set;}
                              public ICollection<Run> Runs {get;set;}
                            }
                            
                            public class Run
                            {
                              public int Id {get; set;}
                              public int RequestId {get; set;}
                              public Pipeline Pipeline {get;set;}
                            }
                            

                            Run 与 Pipeline 是多对一的关系(一个 Pipeline 可以运行多次)

                            在我的RunService 中,我将 DbContex 注入为context。 DbContext 有一个Runs DbSet。我在RunService中实现了这个方法:

                            public async Task<Run> CreateAndInit(int requestId, int pplId)
                            {
                              Pipeline pipeline = await pipelineService.Get(pplId).FirstOrDefaultAsync().ConfigureAwait(false);
                              Run newRun = new Run {RequestId = requestId, Pipeline = pipeline};
                              context.Runs.Add(newRun);
                              await context.SaveChangesAsync().ConfigureAwait(false); // got exception in this line
                              return newRun;
                            }
                            

                            当方法执行时,我得到了这个异常:

                            Exception has occurred: CLR/Microsoft.EntityFrameworkCore.DbUpdateException
                            Exception thrown: 'Microsoft.EntityFrameworkCore.DbUpdateException' in System.Private.CoreLib.dll: 'An error occurred while updating the entries. See the inner exception for details.'
                             Inner exceptions found, see $exception in variables window for more details.
                             Innermost exception     Microsoft.Data.SqlClient.SqlException : Cannot insert explicit value for identity column in table 'Pipelines' when IDENTITY_INSERT is set to OFF.
                            

                            对我来说,解决方案是将对象和关系的创建分开

                            public async Task<Run> CreateAndInit(int requestId, int pplId)
                            {
                              Pipeline pipeline = await pipelineService.Get(pplId).FirstOrDefaultAsync().ConfigureAwait(false);
                              Run newRun = new Run {RequestId = requestId};
                              context.Runs.Add(newRun);
                              newRun.Pipeline = pipeline; // set the relation separately
                              await context.SaveChangesAsync().ConfigureAwait(false); // no exception
                              return newRun;
                            }
                            

                            【讨论】:

                              【解决方案25】:

                              即使一切正确,如果 Identity 列的数据类型不是 int 或 long,也会出现此错误。我的身份列是十进制的,虽然我只保存 int 值(我的错)。更改数据库和底层模型中的数据类型为我解决了这个问题。

                              【讨论】:

                                【解决方案26】:

                                在 [HttpPost] 方法上设置断点并检查传递给 Id 属性的值。如果它不是零,则会发生此错误。

                                【讨论】:

                                【解决方案27】:

                                第一件事……

                                您首先需要知道为什么会出现错误。

                                让我们看一个 JSON 数据的简单 HttpPost,如下所示:

                                {
                                "conversationID": 1, 
                                "senderUserID": 1, 
                                "receiverUserID": 2,
                                "message": "I fell for the wrong man!",
                                "created":"2022-02-14T21:18:11.186Z"
                                }
                                

                                如果您在连接到 SQLServer 或任何其他数据库服务器时使用实体框架核心生成数据库,则数据库会自动负责更新和自动生成身份列的键/唯一标识符,在大多数情况下是整数值自动递增。

                                为了使用内置约定安全地发布您的数据,让您处于更安全的状态,只需从您要发送到数据库的数据中删除 ID 字段,然后让数据库引擎和 ef-core 完成繁重的工作提升他们的设计目的。

                                所以发布数据的正确方法是:

                                { 
                                    "senderUserID": 1, 
                                    "receiverUserID": 2,
                                    "message": "I fell for the wrong man!",
                                    "created":"2022-02-14T21:18:11.186Z"
                                    }
                                

                                你会注意到我取出了 ConversationID。

                                您可以在本网站了解更多关于实体框架的信息:https://entityframeworkcore.com

                                我希望您在应用中更多地遵守约定而不是配置。知道如何使用已经过验证的标准和惯例来做事,将为您节省大量的工作时间。

                                【讨论】:

                                  【解决方案28】:

                                  如果您使用接口并以通用方式实现 savechanges 方法,则使用非类型化 DBContext 或 DBSet 引发的问题

                                  如果这是你的情况,我建议以强类型 DBContex 为例

                                  MyDBContext.MyEntity.Add(mynewObject)
                                  

                                  那么.Savechanges 就可以了

                                  【讨论】:

                                    【解决方案29】:

                                    只需删除拖到 .dbml 文件中的表,然后再次重新拖动它们。然后清理解决方案>重建解决方案>构建解决方案。

                                    这对我有用。

                                    我没有自己制作表格,我使用的是 VS 和 SSMS,我点击此链接获取 ASP.NET Identity:https://docs.microsoft.com/en-us/aspnet/identity/overview/getting-started/adding-aspnet-identity-to-an-empty-or-existing-web-forms-project

                                    【讨论】:

                                      猜你喜欢
                                      • 2016-08-18
                                      • 2019-03-10
                                      • 2011-08-26
                                      • 2017-12-17
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多