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

时间:2016-11-30 11:36:35

标签: sql-server node.js node-mssql

我正在尝试将一批CREATE TRIGGER个语句作为要在迁移数据库时处理的字符串发送

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”附近的语法不正确

当只发送第一个触发器时工作正常。不确定是什么问题。

3 个答案:

答案 0 :(得分:2)

根据documentation on batches,您不能在同一批次中放置多个CREATE TRIGGER语句:

  

创建默认,创建功能,创建过程,创建规则,创建模式,创建触发器和创建视图语句不能与批处理中的其他语句组合。 CREATE语句必须启动批处理。该批次中的所有其他语句将被解释为第一个CREATE语句定义的一部分。

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

我假设您要从Node创建并执行数据库创建脚本。

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

另一种选择是使用GO分隔符创建单个SQL脚本,并使用SQL Server的命令行工具执行它。这样更易于维护,因为您可以保存脚本并对其进行版本控制,检测更改等。

第三种选择是使用SQL Server的开发工具为数据库建模。数据库项目支持版本控制和验证。但主要的优点是SSDT可以生成一个脚本来更新目标数据库,类似于Redgate的工具。 SSDT具有中等智能,可以识别在工具本身内执行的重命名等,并使用例如sp_rename而不是删除一列并创建一个新列。

另一个优点是SSDT生成dacpac,本质上是一个已编译的模型,可用于对目标数据库进行差异化并生成更新脚本。

这使得连续数据库部署更容易批次。它由AppVeyorTFS支持。 TeamCity以及可以运行sqlpackage工具的任何工具/服务。

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

答案 1 :(得分:1)

对于任何希望做这个 - GO并不总是运行多个批次,因为它不是T-SQL一个很好的解决方案,它只能通过SSMS和一些命令行工具的理解。例如,你不能在存储过程或函数中使用它。

这是否表示存储过程和函数被限制为单批?

它很少提到在会议室安静的音调之外,但实际上你可以说是保证在任何地方工作单的T-SQL脚本中运行多个批次。动态SQL。 EXEC sp_executesql @sql 始终在其自己的批次中运行。您可以进一步环绕多个EXEC sp_executesql与交易电话,如果您需要。动态SQL是一个痛苦的写,但它可以让你做这样的事情在一个存储过程多批,否则是不可能的。

答案 2 :(得分:0)

某些陈述在它们之前没有任何内容。在这种情况下,在SSMS中,使用GO来指示批处理的结束(这有效地清除了缓冲区,因此将清除在GO之前声明的任何变量。)

如果你在SSMS,你可以:

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

如果您不在SSMS之外,则必须发送单独的命令,或者将它们放入T-SQL中的字符串并执行字符串:

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)