简单触发器初学者防止删除
Posted
技术标签:
【中文标题】简单触发器初学者防止删除【英文标题】:Simple Trigger Beginner Prevent from delete 【发布时间】:2016-02-03 11:06:09 【问题描述】:我正在尝试编写我的第一个触发器。我有元素表。我里面的记录很少。很少有记录在 1 上具有复选框,在 0 上具有复选框。
我正在尝试制作触发器,以防止删除复选框为 1 (elm_intcolumn1
) 的记录。
触发器正在工作,但我无法使用复选框 0 删除记录。触发器正在阻止我元素上的所有记录。
ALTER TRIGGER [dbo].[test]
ON [dbo].[elements]
INSTEAD OF DELETE
AS
BEGIN
SELECT CASE
WHEN elm_intcolumn1 = 1
THEN 0
WHEN elm_intcolumn1 = 0
THEN 1
END
FROM elements
BEGIN
RAISERROR ('błąd', 16, 1)
ROLLBACK TRANSACTION
RETURN;
END
END
【问题讨论】:
每个语句触发一次,而不是每个行触发一次。如果有人写了一个DELETE
,它(至少)删除了elm_intcolumn1
为1 的一行,并且(至少)删除了为0 的一行,那么你想发生什么?
【参考方案1】:
检查虚拟表DELETED
和INSERTED
-
CREATE TABLE dbo.[elements] (
id INT IDENTITY PRIMARY KEY,
elm_intcolumn1 BIT
)
GO
INSERT INTO dbo.[elements] (elm_intcolumn1)
VALUES (0), (1)
GO
ALTER TRIGGER dbo.test
ON dbo.[elements]
AFTER DELETE
AS
BEGIN
IF EXISTS(
SELECT 1
FROM DELETED
WHERE elm_intcolumn1 = 1
)
BEGIN
RAISERROR ('revert', 16, 1)
ROLLBACK TRANSACTION
END
END
GO
SELECT * FROM dbo.[elements]
DELETE dbo.[elements]
WHERE id = 2
删除第二条记录时:
Msg 50000, Level 16, State 1, Procedure test, Line 39
revert
Msg 3609, Level 16, State 1, Line 29
The transaction ended in the trigger. The batch has been aborted.
【讨论】:
但是当我删除具有复选框 0 的记录时,他并没有从元素中删除。我只想防止删除具有复选框 1 的元素。 非常感谢,现在它正在工作,对我来说更清楚触发器是如何工作的:)【参考方案2】:您的解决方案过于复杂。
首先 - 您不需要检查创建触发器的表,而是检查 instead of delete
触发器上下文中可用的名为 deleted
的特殊表。此表包含您要删除的记录。
第二 - 您的检查应该只是“在已删除的表中是否存在具有“elm_intcolumn1 = 1”的记录”。如果是 - 然后抛出异常,如果没有这样的记录 - 然后从表中删除来自 deleted
的所有记录。在这种情况下,您的表应该有一些主键(我假设它在下面的示例中命名为 ID
)。
字面意思是这样的:
if exists(select * from deleted where elm_intcolumn1 = 1)
begin
RAISERROR ('błąd', 16, 1)
ROLLBACK TRANSACTION
RETURN;
end
else
begin
delete from elements where ID in (select ID from deleted)
end
请注意,您必须在此触发器中显式删除表中的记录,因为它是 instead of delete
,而不是 after delete
。
或者,您可以将触发器类型更改为after delete
,这样就不需要在else
条件分支中显式删除。
【讨论】:
以上是关于简单触发器初学者防止删除的主要内容,如果未能解决你的问题,请参考以下文章
Oracle-4 - :超级适合初学者的入门级笔记:plsql,基本语法,记录类型,循环,游标,异常处理,存储过程,存储函数,触发器