分离批处理中运行的多个SQL Server语句

我试图发送一批CREATE TRIGGER语句作为一个string来迁移我的数据库时进行处理

 CREATE TRIGGER [dbo].[triggerBar] ON [dbo].[tableBar] INSTEAD OF UPDATE,INSERT AS BEGIN SET NOCOUNT ON -- Trigger body here.. END; CREATE TRIGGER [dbo].[triggerFoo] ON [dbo].[tableFoo] INSTEAD OF UPDATE,INSERT AS BEGIN SET NOCOUNT ON -- Trigger body here.. END; 

所以我正在用每个语句块来划分; 但我仍然得到这个错误:

关键字“TRIGGER”附近的语法错误

发送只是第一个触发器工作得很好。 不知道什么是错的。

根据批处理文档,不能在同一批次中放置多个CREATE TRIGGER语句:

CREATE DEFAULT,CREATE FUNCTION,CREATE PROCEDURE,CREATE RULE,CREATE SCHEMA,CREATE TRIGGER和CREATE VIEW语句不能与批处理中的其他语句结合使用。 CREATE语句必须启动批处理。 在该批处理中的所有其他语句将被解释为第一个CREATE语句定义的一部分。

GO可以工作,因为它是由SSMS,sqlcmd和SQL Server开发工具所识别的批处理定界符,绝不会发送到服务器。 该工具使用它来批量分割文本并将它们逐个发送到服务器。 事务跨批处理(毕竟是相同的连接),所以可以回滚某些DDL语句。

我假设你想从Node创build并执行一个数据库创build脚本。

一种解决方法是使用与SQL Server工具相同的方法:生成单独的批处理,并逐个针对数据库执行它们。

另一个select是使用GO分隔符创build一个SQL脚本,并使用SQL Server的命令行工具执行它。 这是更可维护的,因为你可以保存和版本的脚本,检测到变化等

第三个选项是使用SQL Server的开发工具来build模您的数据库。 数据库项目支持版本控制和validation。 主要的好处是SSDT可以生成一个脚本来更新一个目标数据库,类似于Redgate的工具。 SSDT是相当聪明的,可以识别在工具本身内部执行的重命名等,使用例如sp_rename而不是删除一列并创build一个新的。

另一个优点是SSDT生成一个dacpac ,本质上是一个编译模型,可以用来dacpac目标数据库和生成更新脚本。

这使连续的数据库部署变得更容易。 它由AppVeyor , TFS支持。 TeamCity和任何可以运行sqlpackage工具的工具/服务。

缺点是SSDT只适用于SQL Server数据库。

某些陈述在他们面前什么也没有。 在这种情况下,在SSMS中,使用GO来指示批次的结束(这将有效地清除缓冲区,所以在GO之前声明的任何variables都将被清除)。

如果你在SSMS,你可以:

 CREATE TRIGGER ... AS ... GO CREATE TRIGGER ... etc 

如果你不在SSMS中,你必须发送单独的命令,或者把它们放到T-SQL的string中,然后执行string:

 DECLARE @Trig1 NVARCHAR(MAX) DECLARE @Trig2 NVARCHAR(MAX) DECLARE @Trig3 NVARCHAR(MAX) SET @Trig1 = 'CREATE TRIGGER ...' SET @Trig2 = 'CREATE TRIGGER ...' SET @Trig3 = 'CREATE TRIGGER ...' EXEC (@Trig1) EXEC (@Trig2) EXEC (@Trig3)