删除语句上重复键行插入错误

时间:2019-04-23 17:25:48

标签: sql sql-server-2014

我正在SQL中执行以下DELETE语句,但收到以下错误消息。

DELETE PSRO
FROM ROLEUSER PSRO
INNER JOIN PS_GH_AD_X_WALK B ON B.OPRID = PSRO.ROLEUSER
INNER JOIN HSDEV185.HSDEV92B.dbo.PS_JOB C ON C.EMPLID = B.GH_AD_EMPLID AND B.GH_AD_EMPLID <> ''
WHERE C.EFFDT = 
(SELECT MAX(A_ED.EFFDT) FROM HSDEV185.HSDEV92B.dbo.PS_JOB A_ED 
WHERE C.EMPLID = A_ED.EMPLID 
AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10)) 


Msg 2601, Level 14, State 1, Procedure ROLEUSER_TR, Line 67
Cannot insert duplicate key row in object 'dbo.AUDIT_ROLEUSR' with unique index 'AUDIT_ROLEUSR'. The duplicate key value is (Native SQL                    , Apr 23 2019  1:15PM, D).
The statement has been terminated.

我很困惑,为什么SQL将我的DELETE命令解释为插入命令?

编辑: 与ROLEUSER表关联的触发器如下。我对触发器不是很熟悉。当通过SQL执行此Delete时,是否有一种方法可以防止插入发生(与在系统中在线进行的删除相反,这是触发器打算使用的)?

ALTER TRIGGER [dbo].[PSROLEUSER_TR] ON [dbo].[ROLEUSER]
FOR INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON
DECLARE @XTYPE CHAR(1), @OPRID CHAR(30)
SET @OPRID = NULL
SELECT @OPRID = case (charindex(',',
cast(context_info as char(128))))
when 0 then 'Native SQL'
else 
substring(cast(context_info as
CHAR(128)),1,(charindex(',',cast(context_info as char(128)))-1))
end
FROM sys.sysprocesses
WHERE spid = @@spid
-- Determine Transaction Type
IF EXISTS (SELECT * FROM DELETED)
BEGIN
SET @XTYPE = 'D'
END

IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF (@XTYPE = 'D')
 BEGIN
  SET @XTYPE = 'U'
 END
ELSE
 BEGIN
  SET @XTYPE = 'I'
 END
END
-- Transaction is a Delete
IF (@XTYPE = 'D')
BEGIN
INSERT INTO PS_AUDIT_PSROLEUSR
(AUDIT_OPRID,AUDIT_STAMP,AUDIT_ACTN,
ROLEUSER,
ROLENAME,
DYNAMIC_SW)
SELECT @OPRID,getdate(),'D',
ROLEUSER,
ROLENAME,
DYNAMIC_SW FROM deleted 
END
-- Transaction is a Insert
IF (@XTYPE = 'I')
BEGIN
INSERT INTO PS_AUDIT_PSROLEUSR
(AUDIT_OPRID,AUDIT_STAMP,AUDIT_ACTN,
ROLEUSER,
ROLENAME,
DYNAMIC_SW)
SELECT @OPRID,getdate(),'A',
ROLEUSER,
ROLENAME,
DYNAMIC_SW FROM inserted 
END
-- Transaction is a Update
IF (@XTYPE = 'U')
BEGIN
-- Before Update
INSERT INTO PS_AUDIT_PSROLEUSR
(AUDIT_OPRID,AUDIT_STAMP,AUDIT_ACTN,
ROLEUSER,
ROLENAME,
DYNAMIC_SW)
SELECT @OPRID,getdate(),'K',
ROLEUSER,
ROLENAME,
DYNAMIC_SW FROM deleted 
-- After Update
INSERT INTO PS_AUDIT_PSROLEUSR
(AUDIT_OPRID,AUDIT_STAMP,AUDIT_ACTN,
ROLEUSER,
ROLENAME,
DYNAMIC_SW)
SELECT @OPRID,getdate(),'N',
ROLEUSER,
ROLENAME,
DYNAMIC_SW FROM inserted 
END

2 个答案:

答案 0 :(得分:0)

使用类似

alter index AUDIT_ROLEUSR on TableName
    rebuild with (ignore_dup_key = on)

或在第67行上检查过程ROLEUSER_TR并确保没有触发器。

编辑:

如果要定期执行此删除操作,可以创建一个过程来禁用索引,删除并重新打开。

答案 1 :(得分:0)

  

有没有一种方法可以防止在通过SQL执行此Delete时发生插入操作(与系统中在线发生的删除操作相反

不直接,不。但是您可以对触发器进行编码,在某些情况下不采取任何措施。例如,如果您将其添加到触发器的开头:

if user_id() = 1 return;

当DBO(数据库所有者或sysadmin)运行命令但为其他任何人运行触发器主体时,它将立即退出。