【发布时间】:2018-07-05 23:59:18
【问题描述】:
我在下面有一个代码,应该将记录插入表中,但不幸的是,如果插入、更新或删除多条记录,此代码将不起作用。我应该如何重写程序代码以遍历所有插入/删除的记录?而且我确实需要使用带有输入参数的存储过程(不仅仅是简单的插入...选择...从...)
IF EXISTS (SELECT * FROM MyDB.sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[MyTable_DEL_UPD_INS]'))
DROP TRIGGER [dbo].[MyTable_DEL_UPD_INS]
GO
CREATE TRIGGER [dbo].[MyTable_DEL_UPD_INS]
ON [MyDB].[dbo].[MyTable]
AFTER DELETE, UPDATE, INSERT
NOT FOR REPLICATION
AS
BEGIN
DECLARE @PKId INT,
@Code VARCHAR(5),
@AuditType VARCHAR(10)
SET @Code = 'TEST'
IF EXISTS (SELECT * FROM deleted d)
AND NOT EXISTS (SELECT * FROM inserted i)
BEGIN
SELECT TOP 1
@PKId = d.[MyTable_PK],
@AuditType = 'DELETE'
FROM
deleted d WITH (NOLOCK)
IF @PKId IS NOT NULL
AND @Code IS NOT NULL
EXEC MyDB.[dbo].[SP_Audit] @PKId, @Code, @AuditType
END
IF EXISTS (SELECT * FROM deleted d)
AND EXISTS (SELECT * FROM inserted i)
BEGIN
SELECT TOP 1
@PKId = d.[MyTable_PK],
@AuditType = 'UPDATE'
FROM
deleted d WITH (NOLOCK)
IF @PKId IS NOT NULL
AND @Code IS NOT NULL
EXEC MyDB.[dbo].[SP_Audit] @PKId, @Code, @AuditType
END
IF NOT EXISTS (SELECT * FROM deleted d)
AND EXISTS (SELECT * FROM inserted i)
BEGIN
SELECT TOP 1
@PKId = d.[MyTable_PK],
@AuditType = 'INSERT'
FROM
deleted d WITH (NOLOCK)
IF @PKId IS NOT NULL
AND @Code IS NOT NULL
EXEC MyDB.[dbo].[SP_Audit] @PKId, @Code, @AuditType
END
END
GO
ALTER TABLE [MyDB].[dbo].[MyTable] ENABLE TRIGGER [MyTable_DEL_UPD_INS]
【问题讨论】:
-
您可以修改 SP_Audit 以接受表值吗?
-
在触发器中有一个循环就像一个非常糟糕的主意。它会严重影响性能。再加上你有一个 SP 的事实,就目前而言,它需要一个进一步的循环才能使用(这样对于多行,你循环遍历每一行),你最终得到一个简单的 @ 987654322@ 包含 100 左右的行,需要大量资源。 SP_Audit 在做什么?你能提供它的SQL吗?如果您必须使用它,这可能意味着您需要更改它;这意味着您可能需要更改引用它的所有内容...
-
另外,
WITH (NOLOCK)不会在您的触发器中实现任何功能。事实上,我建议你删除它;因为它更可能导致问题而不是解决任何问题。 -
我同意你的看法!性能会非常糟糕。 Th SP 只是 Select Into... Insert ... From ... 仅此而已:)。我可能会试图说服我的队友放弃使用 SP。他非常渴望使用它,因为在他看来它很优雅......
-
对 WITH (NOLOCK) 用法的好评。在我的公司里,他们甚至把它放在 CTE 和 Temp 表上。看不到任何意义......我可以说同意在物理对象上更有意义。
标签: sql-server stored-procedures while-loop triggers do-while