如何使用 TRANSACTION 将 CREATE TRIGGER 放入 TRY-CATCH 块中?

Vit*_*liy 2 t-sql sql-server transactions try-catch database-trigger

我不是 SQL 的高级程序员,也许我的问题很愚蠢,但我还没有在谷歌中找到答案。我们有一些 SQL 结构来实现更改包:

...
BEGIN TRY
    BEGIN TRANSACTION;
    <User Code Is Here>
    ...
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ...
END CATCH;
...
Run Code Online (Sandbox Code Playgroud)

如何放置 CREATE TRIGGER 块链而不是<User Code Is Here>没有错误:

-- Table1
CREATE TRIGGER trTable1_Dates ON dbo.Table1
AFTER INSERT, UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   ...
   SET NOCOUNT OFF;
END
GO
...
-- TableN
CREATE TRIGGER trTableN_Dates ON dbo.TableN
AFTER INSERT, UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   ...
   SET NOCOUNT OFF;
END
GO
Run Code Online (Sandbox Code Playgroud)

目的是创建所有触发器或不创建任何触发器,并在失败时在 CATCH 代码块中打印消息。

已编辑

错误是:

  1. 在第一个触发器上BEGIN:SQL80001:'BEGIN' 附近的语法不正确。期待外部。
  2. 第一次触发后,在GO:SQL80001:'GO' 附近的语法不正确。
  3. END TRY:SQL80001:'TRY' 附近的语法不正确。期待对话。
  4. END CATCH:SQL80001:'CATCH' 附近的语法不正确。期待对话。

Dam*_*ver 5

您需要create table在单独的范围/批处理中运行每个语句(因为它必须是批处理中的第一个语句)。因此,您还必须转义触发器定义中的任何引号:

BEGIN TRY
    BEGIN TRANSACTION;
    exec sp_executesql N'CREATE TRIGGER trTable1_Dates ON dbo.Table1
    AFTER INSERT, UPDATE
    AS
    BEGIN
       SET NOCOUNT ON;
       //An empty string in here has to be '''' to escape the quotes
       SET NOCOUNT OFF;
    END'

    exec sp_executesql N'CREATE TRIGGER trTableN_Dates ON dbo.TableN
    AFTER INSERT, UPDATE
    AS
    BEGIN
       SET NOCOUNT ON;
       ...
       SET NOCOUNT OFF;
    END'
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ...
END CATCH;
Run Code Online (Sandbox Code Playgroud)

事务与批次和嵌套范围正交,因此事务也涵盖了在每个范围内发生的所有活动EXEC。

  • @GeorgeMenoutis - 因为 `GO` 不是 T-SQL 构造 - 它告诉客户端工具如何将脚本分成批次以提交给服务器。`TRY`/`CATCH` 块不能跨越批次边界。您的第二批(在 `GO` 之后)以 `CREATE TRIGGER` 开头,因此触发器被创建。 (2认同)