通过 sql 服务中的 OPEN XML 插入数据时触发器不起作用
Triggers not working when inserting data through OPEN XML in sql ser
我已经为 asset_verification 创建了一个触发器。每当在此 table 中插入一条新记录时,由于此触发器,相同的记录将插入 asset_verification_history table。
触发器如下
Create trigger [dbo].[tr_insert_after_asset_verification] on [dbo].[asset_verification]
for insert
As
Begin
declare @verification_id int
declare @id int
declare @audit_id int
declare @date date
declare @status varchar(15)
declare @remarks varchar(200)
declare @creationDate datetime
declare @modificationDate datetime
declare @updatedBy int
declare @audit_action varchar(20)
Select @verification_id = i.verification_id from inserted i
If @verification_id IS NOT NULL
Begin
Select @id = i.id from inserted i
Select @audit_id = i.audit_id from inserted i
Select @date = i.date from inserted i
Select @status = i.status from inserted i
Select @remarks = i.remarks from inserted i
Select @creationDate = i.creationDate from inserted i
Select @modificationDate = i.modificationDate from inserted i
Select @updatedBy = i.updatedBy from inserted i
set @audit_action = 'Insert Record'
INSERT INTO [dbo].[asset_verification_history]
([verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action])
VALUES
(@verification_id
,@id
,@audit_id
,@date
,@status
,@remarks
,@creationDate
,@modificationDate
,@updatedBy
,@audit_action)
End
End
当我使用使用 OPEN XML 的过程将数据插入 asset_verification table 时,此触发器仅适用于第一条记录。对于其余记录,触发器不起作用
程序如下
Create procedure [dbo].[usp_AddVerificationBulkData]
(
@vXML XML
)
As
Begin
DECLARE @DocHandle INT
SET NOCOUNT ON
EXEC sp_xml_preparedocument @DocHandle OUTPUT, @vXML
Update asset_verification
set
audit_id = x.AuditId,
id = x.SerialId,
date = x.VerificationDate,
status = x.Status
,remarks = x.Remarks
,creationDate = x.CreatedOn
,modificationDate = x.ModifiedOn
,updatedBy = x.ModifiedBy
From
asset_verification a
Inner Join
OpenXml(@DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
On a.audit_id = x.AuditId where a.id = x.SerialId;
INSERT INTO [dbo].[asset_verification]
([id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy])
select SerialId,AuditId,VerificationDate,Status,Remarks,CreatedOn,ModifiedOn,ModifiedBy from OpenXml(@DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
where SerialId NOT IN (select a.id from asset_verification a where a.audit_id = x.AuditId);
End
问题:- 如何让这个触发器对通过 Open XML 插入的每条记录起作用?
您犯了典型的错误,认为每行触发一次。他们没有,它是每个动作一次,所以插入的伪 table 包含 all 受动作影响的行。您的触发器需要以基于集合的方式而不是基于行的方式工作。试试这个;
CREATE TRIGGER [dbo].[tr_insert_after_asset_verification] ON [dbo].[asset_verification] FOR INSERT AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[asset_verification_history]
( [verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action]
)
SELECT i.verification_id
,i.id
,i.audit_id
,i.date
,i.status
,i.remarks
,i.creationDate
,i.modificationDate
,i.updatedBy
,'Insert Record'
FROM inserted i
WHERE i.verification_id IS NOT NULL
END
顺便说一句,严格来说,您的原始触发器将记录一行,不一定是第一行。
我已经为 asset_verification 创建了一个触发器。每当在此 table 中插入一条新记录时,由于此触发器,相同的记录将插入 asset_verification_history table。
触发器如下
Create trigger [dbo].[tr_insert_after_asset_verification] on [dbo].[asset_verification]
for insert
As
Begin
declare @verification_id int
declare @id int
declare @audit_id int
declare @date date
declare @status varchar(15)
declare @remarks varchar(200)
declare @creationDate datetime
declare @modificationDate datetime
declare @updatedBy int
declare @audit_action varchar(20)
Select @verification_id = i.verification_id from inserted i
If @verification_id IS NOT NULL
Begin
Select @id = i.id from inserted i
Select @audit_id = i.audit_id from inserted i
Select @date = i.date from inserted i
Select @status = i.status from inserted i
Select @remarks = i.remarks from inserted i
Select @creationDate = i.creationDate from inserted i
Select @modificationDate = i.modificationDate from inserted i
Select @updatedBy = i.updatedBy from inserted i
set @audit_action = 'Insert Record'
INSERT INTO [dbo].[asset_verification_history]
([verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action])
VALUES
(@verification_id
,@id
,@audit_id
,@date
,@status
,@remarks
,@creationDate
,@modificationDate
,@updatedBy
,@audit_action)
End
End
当我使用使用 OPEN XML 的过程将数据插入 asset_verification table 时,此触发器仅适用于第一条记录。对于其余记录,触发器不起作用
程序如下
Create procedure [dbo].[usp_AddVerificationBulkData]
(
@vXML XML
)
As
Begin
DECLARE @DocHandle INT
SET NOCOUNT ON
EXEC sp_xml_preparedocument @DocHandle OUTPUT, @vXML
Update asset_verification
set
audit_id = x.AuditId,
id = x.SerialId,
date = x.VerificationDate,
status = x.Status
,remarks = x.Remarks
,creationDate = x.CreatedOn
,modificationDate = x.ModifiedOn
,updatedBy = x.ModifiedBy
From
asset_verification a
Inner Join
OpenXml(@DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
On a.audit_id = x.AuditId where a.id = x.SerialId;
INSERT INTO [dbo].[asset_verification]
([id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy])
select SerialId,AuditId,VerificationDate,Status,Remarks,CreatedOn,ModifiedOn,ModifiedBy from OpenXml(@DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
where SerialId NOT IN (select a.id from asset_verification a where a.audit_id = x.AuditId);
End
问题:- 如何让这个触发器对通过 Open XML 插入的每条记录起作用?
您犯了典型的错误,认为每行触发一次。他们没有,它是每个动作一次,所以插入的伪 table 包含 all 受动作影响的行。您的触发器需要以基于集合的方式而不是基于行的方式工作。试试这个;
CREATE TRIGGER [dbo].[tr_insert_after_asset_verification] ON [dbo].[asset_verification] FOR INSERT AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[asset_verification_history]
( [verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action]
)
SELECT i.verification_id
,i.id
,i.audit_id
,i.date
,i.status
,i.remarks
,i.creationDate
,i.modificationDate
,i.updatedBy
,'Insert Record'
FROM inserted i
WHERE i.verification_id IS NOT NULL
END
顺便说一句,严格来说,您的原始触发器将记录一行,不一定是第一行。