批量分离多个 SQL 服务器语句 运行

Separating multiple SQL Server statements running in batch

我正在尝试将一批 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;

所以我用 ; 分隔每个语句块,但我仍然收到此错误:

Incorrect syntax near the keyword 'TRIGGER'

仅发送第一个触发器就可以正常工作。不知道怎么回事。

某些语句前面可以没有任何内容。在这种情况下,在 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)

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

CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER, and CREATE VIEW statements cannot be combined with other statements in a batch. The CREATE statement must start the batch. All other statements that follow in that batch will be interpreted as part of the definition of the first CREATE statement.

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

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

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

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

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

另一个优势是 SSDT 生成一个 dacpac,本质上是一个编译模型,可用于与目标数据库进行比较并生成更新脚本。

这使得连续数据库部署很多更容易。 AppVeyor, TFS. TeamCity and any tool/service that can run the sqlpackage 工具支持它。

缺点是 SSDT 仅适用于 SQL 服务器数据库。

对于任何想要这样做的人来说- GO 并不总是 运行 宁多个批次的好解决方案,因为它不是 T-SQL,它只能被 SSMS 和一些命令行理解工具。例如,您不能在存储过程或函数中使用它。

这是否意味着存储过程和函数仅限于单个批处理?

它很少被提及,除了会议厅里的安静声调,但实际上您可以 运行 在保证在任何地方都能工作的单个 T-SQL 脚本中进行多个批处理。动态 SQL。 EXEC sp_executesql @sql 总是 运行 在自己的批次中。如果需要,您还可以用事务包围多个 EXEC sp_executesql 调用。动态 SQL 写起来很痛苦,但它可以让你在一个 sproc 中做多批次的事情,否则这是不可能的。