我想检查[tbl]上是否存在触发器并创建另一个触发器。我试过这种方式,但没有工作。我做错了什么?
IF EXISTS (SELECT * FROM sys.objects WHERE [name] = '[dbo].[trg]' AND [type] = 'TR')
DROP TRIGGER [dbo].[trg] ON [dbo].[tbl]
GO
CREATE TRIGGER [dbo].[trg] ON [dbo].[tbl]
AFTER DELETE
AS
BEGIN
//
END
GO
答案 0 :(得分:35)
[name]
中的sys.objects
字段仅包含实际名称(即trg
),不,包括架构(即dbo
in这种情况)或任何文本限定符(在这种情况下为[
和]
)。
AND,您没有为DROP TRIGGER
指定表名,因为触发器本身就是一个对象(与索引不同)。因此,您需要删除ON
子句(仅用于DDL和Logon触发器)。
IF EXISTS (SELECT * FROM sys.objects WHERE [name] = N'trg' AND [type] = 'TR')
BEGIN
DROP TRIGGER [dbo].[trg];
END;
请注意,您应该在对象名称字符串文字前加N
作为前缀,因为[name]
字段是等于sysname
的{{1}}数据类型。
如果您确实想要合并模式名称,可以使用允许模式名称和文本限定符的NVARCHAR(128)
函数(然后您需要匹配OBJECT_ID()
而不是{{1} }}):
object_id
为了简化,由于对象名称在模式中需要是唯一的,因此您只需要测试其存在性。如果由于某种原因存在具有该名称的不同对象类型,则name
将失败,因为其他对象是,而不是触发器;-)。因此,我使用以下内容:
IF EXISTS (SELECT * FROM sys.objects WHERE [object_id] = OBJECT_ID(N'[dbo].[trg]')
AND [type] = 'TR')
BEGIN
DROP TRIGGER [dbo].[trg];
END;
答案 1 :(得分:4)
如果您使用SQL Server 2016,则可以使用较短的变体。
DROP TRIGGER IF EXISTS [dbo].[trg]
https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-trigger-transact-sql
答案 2 :(得分:0)
你能试试吗
SELECT * FROM sys.objects WHERE [name] = PARSENAME('[dbo].[trg]',1) AND [type] = 'TR'
编辑:
srutzky已经给了你答案并且解释得很清楚,你可以在PARSENAME的帮助下解析这个名字。