无法插入显式值,因为 IDENTITY_INSERT 为 OFF,但无法将 IDENTITY_INSERT 设置为 ON,因为它已经为 ON
Posted
技术标签:
【中文标题】无法插入显式值,因为 IDENTITY_INSERT 为 OFF,但无法将 IDENTITY_INSERT 设置为 ON,因为它已经为 ON【英文标题】:Cannot insert explicit value because IDENTITY_INSERT is OFF, but cannot SET IDENTITY_INSERT to ON because it is already ON 【发布时间】:2013-06-25 05:42:12 【问题描述】:我在数据库Foo
中有一个名为Bar
的表,其中有一个名为ID
的列,它是主键,并且该数据库位于开发SQL Server 上。
我正在尝试将数据从我们的生产服务器复制到开发服务器,以便我可以使用所述数据,因此我执行以下操作:
set IDENTITY_INSERT Foo.dbo.Bar ON
insert into Foo.dbo.Bar
(
ID
,Something
,Else
,Is
,Going
,Horribly
,Wrong
,With
,SQL
)
select
ID
,Something
,Else
,Is
,Going
,Horribly
,Wrong
,With
,SQL
from Production.Foo.dbo.Bar
set IDENTITY_INSERT Foo.dbo.Bar OFF
我得到了错误
消息 8107,第 16 级,状态 1,第 1 行 表 'Foo.dbo.Bar' 的 IDENTITY_INSERT 已打开。无法对表 'Foo.dbo.Bar' 执行 SET 操作。
嗯..好的,所以 IDENTITY_INSERT 已为该表打开。所以我从查询顶部删除了SET IDENTITY_INSERT Foo.dbo.Bar ON
,然后执行它,我得到了这个错误:
消息 544,第 16 级,状态 1,第 1 行 当 IDENTITY_INSERT 设置为 OFF 时,无法为表“Bar”中的标识列插入显式值。
我可以整天执行SET IDENTITY_INSERT Foo.dbo.Bar OFF
,但如果我尝试将其转为ON
,则SQL Server 2012 会说IDENTITY_INSERT
已打开。
【问题讨论】:
是否有可能是从其他会话打开的? 我无法重现此错误。如果IDENTITY_INSERT
为表打开,我可以不断将其设置为打开而不会出现错误,类似地,如果它关闭,我可以将其设置为关闭,唯一不能将其设置为打开的情况是它是否存在同一会话中的另一个表。如您所见in this fiddle 前 3 批工作正常,关闭并再次打开多次,只有 4 批失败。
我也无法重新创建此错误。要么 1)这是一个不起眼的 SQL Server 错误(不太可能),要么 2)它与一些我现在无法测试的分布式事务上下文有关(不太可能),或者 3)您以某种方式误读了实际名称/情况.
我设法通过在新的新查询窗口中执行我的查询来解决我的问题。感谢@AaronBertrand 让我走上正轨。
仔细检查错误中的表名是否与消息中的表名匹配。每次它可以引用不同的表时都会让我明白,因为一次只能打开一个表的 identity_insert。
【参考方案1】:
有趣 - 我刚刚在我全新的 ss2012 数据库中的 4 个表中的 3 个表中遇到了完全相同的问题。
所以我重写了表格创建脚本,用“set identity on”和“set identity off”将我的插入括起来,它可以工作。似乎 ss 一次只想处理一个表的身份,即在所有其他表都已关闭之前,您无法设置新的表身份。
类似这样的:
create table Employers
(
id int PRIMARY KEY IDENTITY ,
companyid nvarchar(50) not null,
companyName nvarchar(80) not null,
address nvarchar(80),
Phone nvarchar(10),
);
SET IDENTITY_INSERT employers ON;
insert into Employers(id,companyid,companyName,address,Phone)
Values
(...),
(...)
SET IDENTITY_INSERT employers OFF;
create table customers
(
...
【讨论】:
【参考方案2】:我实际上找到了一个不同的解决方案。这实际上与 Msg 8101 不同,特定于表标识未设置为 ON。
要解决此问题,您需要删除 master 数据库中的架构和同名表。
我有一个模板脚本,它创建一个数据库和表并将数据插入到这些表中,例如:
USE master
GO
CREATE DATABASE [mydb] ON PRIMARY
( NAME = N'mydb', FILENAME = N'C:\SQLDATA\mydb.mdf' , SIZE = 5072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'mydb_log', FILENAME = N'C:\SQLDATA\mydb_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
COLLATE SQL_Latin1_General_CP1_CI_AS
GO
USE [mydb]
GO
CREATE SCHEMA [myschema] AUTHORIZATION [dbo]
GO
CREATE TABLE [myschema].[mytable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[SOMETHING] [int] NOT NULL,
CONSTRAINT [PK_mytable] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
)
GO
SET IDENTITY_INSERT [myschema].[mytable] ON
GO
INSERT [myschema].[mytable] ([ID], [SOMETHING]) VALUES (1,2)
GO
SET IDENTITY_INSERT [myschema].[mytable] OFF
GO
问题是在数据库创建过程中,由于“设备激活”错误(对将创建 MDF 文件的文件夹的权限)或数据库文件大小,语句失败。脚本继续,但改为在 master 数据库中创建模式和表。在我意识到错误后,我停止了脚本并尝试在修复了创建问题的情况下再次运行它。
然后我得到了错误。
Msg 8107, Level 16, State 1, Line 2
IDENTITY_INSERT is already ON for table 'master.myschema.mytable'. Cannot perform SET operation for table 'myschema.mytable'.
Msg 544, Level 16, State 1, Line 2
Cannot insert explicit value for identity column in table 'mytable' when IDENTITY_INSERT is set to OFF.
我不是 SQL Server 专家,但我认为它首先在 master 数据库中查找架构,并且由于找到了此架构并且在当前会话中 IDENTITY 已打开,因此会产生此错误消息。
删除主数据库中错误创建的模式和表后,我的脚本运行成功。
【讨论】:
不知何故,我的脚本在主数据库中创建了表,而不是在我的数据库中。正如您指出的那样删除它们就可以了。谢谢!!!您会注意到问题是:为 Foo.dbo 插入... 已打开。就我而言,它是在说:为 master.dbo 插入 ... 已开启。【参考方案3】:我遇到了完全相同的错误。我使用的是linq-to-sql
,最初生成的表和 dbml 文件在主键上没有标识列。
后来我将主键更新为 Identity 列,但忘记更新 dbml 文件。
当 IDENTITY_INSERT 设置为 OFF 时,无法为表 'BLAH' 中的标识列插入显式值
解决方法是有趣地更新 dbml 文件...
【讨论】:
以上是关于无法插入显式值,因为 IDENTITY_INSERT 为 OFF,但无法将 IDENTITY_INSERT 设置为 ON,因为它已经为 ON的主要内容,如果未能解决你的问题,请参考以下文章
无法添加表行,因为“当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'Users' 中插入标识列的显式值”错误
无法插入显式值,因为 IDENTITY_INSERT 为 OFF,但无法将 IDENTITY_INSERT 设置为 ON,因为它已经为 ON