2016-11-07 56 views
1

获取以下错误:(第21行是声明语句)。标识插入 - 错误消息

Msg 544, Level 16, State 1, Procedure insert_employee_details, Line 21
Cannot insert explicit value for identity column in table 'DB_Actions' when IDENTITY_INSERT is set to OFF.

这是我曾尝试:

SET IDENTITY_INSERT DB_Actions ON; 

但后来我得到这个错误:

Msg 8107, Level 16, State 1, Line 31
IDENTITY_INSERT is already ON for table 'StacysDB.dbo.Employee_Details'. Cannot perform SET operation for table 'DB_Actions'.

这不会使得感知到我。首先它不起作用,因为身份插入关闭。然后,当我尝试打开它时,它已经打开了。

我知道这是一个常见的错误,所以我尝试了一个确认的解决方案,在插入值之前重新创建表并设置标识插入,然后返回并插入值,但我得到了相同的错误(Msg 8107)。

感谢您的任何帮助。

--1 
--CREATE TABLE DB_Actions 
--(
--Id numeric(5,0) IDENTITY(1,1) PRIMARY KEY, 
--Table_Name varchar(20), 
--Action_Name varchar(10), 
--User_Name varchar(50), 
--Done_ON datetime, 
--Record_Id numeric(5,0) 
--); 

--2 
--INSERT TRIGGER 
--CREATE TRIGGER insert_employee_details 
--ON Employee_Details 
--FOR INSERT 
--AS 
--DECLARE @id int, @name varchar(20) 
--SELECT @id = Emp_Id, @name = Emp_First_Name FROM inserted 
--INSERT INTO DB_Actions(Id, Table_Name, Action_Name, User_Name, 
    --Done_ON, Record_Id) 
--VALUES(@id, 
    -- 'Employee_Details', 
    -- 'INSERT', 
    -- @name, 
    -- getdate(), 
    -- @id 
--); 


INSERT INTO Employee_Details(Emp_Id, Emp_First_Name, Emp_Middle_Name, Emp_Last_Name, Emp_Address1, Emp_Address2, Emp_Country_Id, Emp_State_Id, Emp_City_Id, Emp_Zip, Emp_Mobile, Emp_Gender, Desig_Id, Emp_DOB, Emp_JoinDate, Emp_Active) 
VALUES(9000, 'A', 'B', 'C', 'D', 'E', 2, 3, 4, 44444, 4444444, 1, 3333, getdate(), getdate(), 0); 
+0

我也读过断开和重新连接可以工作。但事实并非如此。 –

+0

在这里稍微退一步,你是否真的需要'Id'作为一个'IDENTITY'列呢?它看起来像某种类型的审计表,为什么不把它变成一个普通的“INT”列呢? – DavidG

+0

它需要是身份和主键。我试图删除我的插入声明中的Id列,但无法让它工作 –

回答

0

IDENTITY_INSERT选项并不打算用于您的日常处理。 IDENTITY_INSERT仅作为临时解决方法。例如,您需要还原意外删除的值。如果您必须将显式值插入标识字段作为日常处理的一部分,则必须重新考虑解决方案。

实现此目的的最简单方法是将显式值存储在另一个字段中,并将标识保留给要管理的SQL Server。在您的解决方案中,这意味着从触发器插入语句中删除DB_Actions.ID字段(您已经在record_id中存储了ID)。

此外,插入的表可以返回多个记录,因此您不应该尝试将其存储在单个变量中。而是使用select语句插入。这也将使你的代码更具可读性。

因此,如下解决这个问题改变你的触发:

CREATE TRIGGER insert_employee_details 
ON Employee_Details 
FOR INSERT 
AS 

INSERT INTO DB_Actions(Table_Name, Action_Name, User_Name, Done_ON, Record_Id) 
SELECT 'Employee_Details', 'INSERT', Emp_First_Name, getdate(), Emp_Id 
FROM inserted; 

如果你的SQL Server 2012或更高版本,另一种解决方案是使用SEQUENCE对象,而不是身份。 SEQUENCE为您提供了更大的灵活性,并解决了许多身份属性问题。

另请注意,DB_Actions中的User_Name字段可能是用于执行操作的系统用户,而不是表中的员工姓名(您始终可以通过查询带有记录标识的原始表来获取后者)。因此,不要考虑Emp_First_Name字段,请考虑使用USER_NAME()内置的函数。

+0

我同意这是帮助重新设计架构的所有有用和必要的建议,我们被要求提供“任何帮助”,但这实际上并没有回答为什么无法设置IDENTITY_INSERT的问题。正如Murthy所述,此功能一次只能为一个表设置,并且已经为Employee_Details表设置,因此无法为DB_Actions表打开。也许你可以在你的回答中加入一些关于这个的东西 –

+0

@DavidDubois,IDENTITY_INSERT选项并不打算用于日常的处理。 IDENTITY_INSERT仅作为临时解决方法。例如,您需要还原意外删除的值。如果您发现自己必须将显式值插入标识字段作为常规处理的一部分,则需要重新考虑解决方案。我昨天绝对同意 – under

+0

。 –