如何使用Microsoft SQL Server Management Studio为数据库中的所有触发器生成脚本
我想生成一个SQL脚本,其中包含创建数据库中存在的所有触发器的SQL。触发器是通过SSMS查询窗格直接添加的,因此,除了数据库本身上的触发器之外,目前没有其他源 我已经尝试过这样的方法:右键单击数据库,选择如何使用Microsoft SQL Server Management Studio为数据库中的所有触发器生成脚本,sql,sql-server-2008,triggers,Sql,Sql Server 2008,Triggers,我想生成一个SQL脚本,其中包含创建数据库中存在的所有触发器的SQL。触发器是通过SSMS查询窗格直接添加的,因此,除了数据库本身上的触发器之外,目前没有其他源 我已经尝试过这样的方法:右键单击数据库,选择Tasks->Generate Scripts,然后使用“为整个数据库和所有对象编写脚本”选项。虽然这会为表和约束创建SQL脚本,但不会为触发器生成SQL 我还了解到,我可以右键单击数据库中的每个触发器并选择GenerateSQL脚本选项,但目前有46个表正在接受审核(用于插入、更新和删除)
Tasks->Generate Scripts
,然后使用“为整个数据库和所有对象编写脚本”选项。虽然这会为表和约束创建SQL脚本,但不会为触发器生成SQL
我还了解到,我可以右键单击数据库中的每个触发器并选择GenerateSQL脚本选项,但目前有46个表正在接受审核(用于插入、更新和删除)
不是为46个表中的每个表手动生成插入、更新和删除触发器脚本,而是有更简单的方法吗?或者,我应该开始单击、复制和粘贴吗?这个怎么样
从syscomments中选择文本,其中的文本类似于“%CREATE TRIGGER%”
编辑-根据jj下面的评论,
syscomments
已被弃用,并将在将来删除。请使用上面列出的基于向导或基于脚本的解决方案继续前进:)数据库->任务->生成脚本->下一步->下一步
在选择脚本选项UI上,在表/视图选项标题下,将脚本触发器设置为True
我知道答案已经被接受,但我想为由于某种原因SSMS向导无法生成触发器脚本的情况提供另一种解决方案(在我的例子中是MSSQLS2008R2) 此解决方案基于上面的想法,但如果触发器超过4000个字符,则使用“sql_模块”提供触发器的完整代码(限制“syscomments”视图的“text”列)
右键单击结果网格,然后“将结果另存为…”保存到保留格式的文件中为所有触发器编写脚本您可以定义存储过程:
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
-- Procedure:
-- [dbo].[SYS_ScriptAllTriggers]
--
-- Parameter:
-- @ScriptMode bit
-- possible values:
-- 0 - Script ALTER only
-- 1 - Script CREATE only
-- 2 - Script DROP + CREATE
ALTER PROCEDURE [dbo].[SYS_ScriptAllTriggers]
@ScriptMode int = 0
AS
BEGIN
DECLARE @script TABLE (script varchar(max), id int identity (1,1))
DECLARE
@SQL VARCHAR(8000),
@Text NVARCHAR(4000),
@BlankSpaceAdded INT,
@BasePos INT,
@CurrentPos INT,
@TextLength INT,
@LineId INT,
@MaxID INT,
@AddOnLen INT,
@LFCR INT,
@DefinedLength INT,
@SyscomText NVARCHAR(4000),
@Line NVARCHAR(1000),
@UserName SYSNAME,
@ObjID INT,
@OldTrigID INT;
SET NOCOUNT ON;
SET @DefinedLength = 1000;
SET @BlankSpaceAdded = 0;
SET @ScriptMode = ISNULL(@ScriptMode, 0);
-- This Part Validated the Input parameters
DECLARE @Triggers TABLE (username SYSNAME NOT NULL, trigname SYSNAME NOT NULL, objid INT NOT NULL);
DECLARE @TrigText TABLE (objid INT NOT NULL, lineid INT NOT NULL, linetext NVARCHAR(1000) NULL);
INSERT INTO
@Triggers (username, trigname, objid)
SELECT DISTINCT
OBJECT_SCHEMA_NAME(B.id), B.name, B.id
FROM
dbo.sysobjects B, dbo.syscomments C
WHERE
B.type = 'TR' AND B.id = C.id AND C.encrypted = 0;
IF EXISTS(SELECT C.* FROM syscomments C, sysobjects O WHERE O.id = C.id AND O.type = 'TR' AND C.encrypted = 1)
BEGIN
insert into @script select '/*';
insert into @script select 'The following encrypted triggers were found';
insert into @script select 'The procedure could not write the script for it';
insert into
@script
SELECT DISTINCT
'[' + OBJECT_SCHEMA_NAME(B.id) + '].[' + B.name + ']' --, B.id
FROM
dbo.sysobjects B, dbo.syscomments C
WHERE
B.type = 'TR' AND B.id = C.id AND C.encrypted = 1;
insert into @script select '*/';
END;
DECLARE ms_crs_syscom CURSOR LOCAL forward_only FOR
SELECT
T.objid, C.text
FROM
@Triggers T, dbo.syscomments C
WHERE
T.objid = C.id
ORDER BY T.objid,
C.colid
FOR READ ONLY;
SELECT @LFCR = 2;
SELECT @LineId = 1;
OPEN ms_crs_syscom;
SET @OldTrigID = -1;
FETCH NEXT FROM ms_crs_syscom INTO @ObjID, @SyscomText;
WHILE @@fetch_status = 0
BEGIN
SELECT @BasePos = 1;
SELECT @CurrentPos = 1;
SELECT @TextLength = LEN(@SyscomText);
IF @ObjID <> @OldTrigID
BEGIN
SET @LineID = 1;
SET @OldTrigID = @ObjID;
END;
WHILE @CurrentPos != 0
BEGIN
--Looking for end of line followed by carriage return
SELECT @CurrentPos = CHARINDEX(CHAR(13) + CHAR(10), @SyscomText, @BasePos);
--If carriage return found
IF @CurrentPos != 0
BEGIN
WHILE ( ISNULL(LEN(@Line), 0) + @BlankSpaceAdded + @CurrentPos - @BasePos + @LFCR ) > @DefinedLength
BEGIN
SELECT @AddOnLen = @DefinedLength - (ISNULL(LEN(@Line), 0) + @BlankSpaceAdded );
INSERT
@TrigText
VALUES
( @ObjID, @LineId, ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N''));
SELECT
@Line = NULL,
@LineId = @LineId + 1,
@BasePos = @BasePos + @AddOnLen,
@BlankSpaceAdded = 0;
END;
SELECT @Line = ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @CurrentPos - @BasePos + @LFCR), N'');
SELECT @BasePos = @CurrentPos + 2;
INSERT
@TrigText
VALUES
( @ObjID, @LineId, @Line );
SELECT @LineId = @LineId + 1;
SELECT @Line = NULL;
END;
ELSE
--else carriage return not found
BEGIN
IF @BasePos <= @TextLength
BEGIN
/*If new value for @Lines length will be > then the
**defined length
*/
WHILE ( ISNULL(LEN(@Line), 0) + @BlankSpaceAdded + @TextLength - @BasePos + 1 ) > @DefinedLength
BEGIN
SELECT @AddOnLen = @DefinedLength - ( ISNULL(LEN(@Line), 0 ) + @BlankSpaceAdded );
INSERT
@TrigText
VALUES
( @ObjID, @LineId, ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N''));
SELECT
@Line = NULL,
@LineId = @LineId + 1,
@BasePos = @BasePos + @AddOnLen,
@BlankSpaceAdded = 0;
END;
SELECT @Line = ISNULL(@Line, N'') + ISNULL(SUBSTRING(@SyscomText, @BasePos, @TextLength - @BasePos+1 ), N'');
IF LEN(@Line) < @DefinedLength AND CHARINDEX(' ', @SyscomText, @TextLength + 1) > 0
BEGIN
SELECT
@Line = @Line + ' ',
@BlankSpaceAdded = 1;
END;
END;
END;
END;
FETCH NEXT FROM ms_crs_syscom INTO @ObjID, @SyscomText;
END;
IF @Line IS NOT NULL
INSERT
@TrigText
VALUES
( @ObjID, @LineId, @Line );
CLOSE ms_crs_syscom;
insert into @script select '-- You should run this result under dbo if your triggers belong to multiple users';
insert into @script select '';
IF @ScriptMode = 2
BEGIN
insert into @script select '-- Dropping the Triggers';
insert into @script select '';
insert into @script
SELECT
'IF EXISTS(SELECT * FROM sysobjects WHERE id = OBJECT_ID(''[' + username + '].[' + trigname + ']'')'
+ ' AND ObjectProperty(OBJECT_ID(''[' + username + '].[' + trigname + ']''), ''ISTRIGGER'') = 1)'
+ ' DROP TRIGGER [' + username + '].[' + trigname +']' + CHAR(13) + CHAR(10)
+ 'GO' + CHAR(13) + CHAR(10)
FROM
@Triggers;
END;
IF @ScriptMode = 0
BEGIN
update
@TrigText
set
linetext = replace(linetext, 'CREATE TRIGGER', 'ALTER TRIGGER')
WHERE
upper(left(replace(ltrim(linetext), char(9), ''), 14)) = 'CREATE TRIGGER'
END
insert into @script select '----------------------------------------------';
insert into @script select '-- Creation of Triggers';
insert into @script select '';
insert into @script select '';
DECLARE ms_users CURSOR LOCAL forward_only FOR
SELECT
T.username,
T.objid,
MAX(D.lineid)
FROM
@Triggers T,
@TrigText D
WHERE
T.objid = D.objid
GROUP BY
T.username,
T.objid
FOR READ ONLY;
OPEN ms_users;
FETCH NEXT FROM ms_users INTO @UserName, @ObjID, @MaxID;
WHILE @@fetch_status = 0
BEGIN
insert into @script select 'setuser N''' + @UserName + '''' + CHAR(13) + CHAR(10);
insert into @script
SELECT
'-- Text of the Trigger' =
CASE lineid
WHEN 1 THEN 'GO' + CHAR(13) + CHAR(10) + linetext
WHEN @MaxID THEN linetext + 'GO'
ELSE linetext
END
FROM
@TrigText
WHERE
objid = @ObjID
ORDER
BY lineid;
insert into @script select 'setuser';
FETCH NEXT FROM ms_users INTO @UserName, @ObjID, @MaxID;
END;
CLOSE ms_users;
insert into @script select 'GO';
insert into @script select '------End ------';
DEALLOCATE ms_crs_syscom;
DEALLOCATE ms_users;
select script from @script order by id
END
使用我自己的版本,结合在这里找到的答案和其他帖子的答案(找不到原始问题)
select OBJECT_NAME(parent_obj) AS table_name,sysobj.name AS trigger_name,
[definition],'GO'
from sys.sql_modules m
inner join sysobjects sysobj on sysobj.id=m.object_id
INNER JOIN sys.tables t ON sysobj.parent_obj = t.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE sysobj.type = 'TR' and sysobj.name like 'NAME_OF_TRIGGER'
order by sysobj.name
这看起来确实会拉回触发器,但是,所有内容都在表的一行中,并且没有格式化。KPL的回答帮了我的忙。不过谢谢你的回答。我不知道syscomments表。很有趣。我没有想到这一点,但这是个好主意:)-1结果不包含我的触发器的全部文本。@MAW74656-叔叔。。。我想我的答案是为了更快速、更肮脏地使用GUI查找不带触发器的触发器。公认的答案可能最适合大多数人。然而,有时有一个低级的替代品是很好的。看起来伊戈尔比我走得更远,在这一点上,我可能会同意他的观点。但是,我会留下我的答案供参考。简要说明:syscomments已被弃用(将在SQL 2014后的某个时间删除),Microsoft建议在SSMS2012中使用sys.SQL_modules,通过单击“设置脚本选项”步骤中的“高级”可以找到“选项”对话框。如果只希望生成触发器,如何使用此对话框?选择sch.name作为架构名称,parent.name作为表名称,obj.name作为触发器名称,m.[定义]作为触发器,sys.sql\u模块中的定义为m internal JOIN sys.objects AS obj ON obj.object\u id=m.object\u id internal JOIN sys.objects AS parent.object\u id=obj.parent\u object\u id internal JOIN sys.schemas AS sch ON sch.schema\u id=parent.schema\u id其中obj.type='TR'
SET nocount ON
DECLARE @return_value INT
EXEC @return_value = [dbo].[SYS_ScriptAllTriggers] @InclDrop = 1
SELECT 'Return Value' = @return_value
select OBJECT_NAME(parent_obj) AS table_name,sysobj.name AS trigger_name,
[definition],'GO'
from sys.sql_modules m
inner join sysobjects sysobj on sysobj.id=m.object_id
INNER JOIN sys.tables t ON sysobj.parent_obj = t.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE sysobj.type = 'TR' and sysobj.name like 'NAME_OF_TRIGGER'
order by sysobj.name