【问题标题】:GO causes error when used in EXEC: "Incorrect syntax near 'GO'."GO 在 EXEC 中使用时会导致错误:“'GO' 附近的语法不正确。”
【发布时间】:2014-07-06 05:51:46
【问题描述】:

我创建了这个存储过程,它为我的所有表动态创建相同的触发器:

USE [MyDatabase]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

--Drop Stored Procedure
BEGIN TRY
     DROP PROCEDURE [dbo].[sp_CreateDataChangedTrigger]
END TRY
BEGIN CATCH
END CATCH
GO

--Create Stored Procedure

-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================

-- =============================================
-- Author:      Scott Bass
-- Create date: 06JUL2014
-- Description: Create Data Change triggers
-- =============================================
CREATE PROCEDURE sp_CreateDataChangedTrigger
    -- Add the parameters for the stored procedure here
    @TableName varchar(255), 
    @TableKey  varchar(255),
    @Debug     bit=1
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

     DECLARE @SQL varchar(max);

     SET @SQL = '
--Drop Trigger
BEGIN TRY
     DROP TRIGGER [dbo].[TR_' + @TableName + '_Audit]
END TRY
BEGIN CATCH
END CATCH
GO

--Create Trigger
CREATE TRIGGER [dbo].[TR_' + @TableName + '_Audit]
     ON [dbo].[' + @TableName + ']
     AFTER INSERT, UPDATE, DELETE
AS
BEGIN
     SET NOCOUNT ON
     DECLARE @event_type [char]

     --Get Event Type
     IF EXISTS(SELECT * FROM INSERTED)
     IF EXISTS(SELECT * FROM DELETED)
          SELECT @event_type = ''U''
     ELSE
          SELECT @event_type = ''I''
     ELSE
     IF EXISTS(SELECT * FROM deleted)
          SELECT @event_type = ''D''
     ELSE
     --no rows affected - cannot determine event
          SELECT @event_type = ''K''

     IF @event_type IN (''I'',''U'') BEGIN
          DECLARE @CurrentUserID INT;
          SELECT  @CurrentUserID = u.UserID
          FROM    [dbo].[dim_Users] u
          WHERE   u.[Username] = dbo.udfUserName()

          UPDATE  t
          SET     DateModified = GETDATE(),
                  WhoModifiedID = @CurrentUserID
          FROM    INSERTED e
          JOIN    [dbo].[' + @TableName + '] t ON e.[' + @TableKey + '] = t.[' + @TableKey + ']
     END

     IF @event_type = ''D'' BEGIN
          no_op:  --Nothing for now
     END
END
GO
';

     IF @Debug=1 BEGIN
          set nocount on;
          print @SQL;
     END
     ELSE BEGIN
          exec(@SQL);
     END    
END
GO

如果我使用调试选项调用 SP:

SET NOCOUNT ON;

DECLARE @return_value int

EXEC    @return_value = [dbo].[sp_CreateDataChangedTrigger]
        @TableName = N'dim_Status',
        @TableKey = N'StatusID',
        @Debug = 1

SELECT  'Return Value' = @return_value

GO

然后从 Messages 窗口提交结果,它工作正常。

但是,当我关闭 @Debug 开关时,我收到以下错误消息:

消息 102,第 15 级,状态 1,第 10 行
“GO”附近的语法不正确。
消息 111,第 15 级,状态 1,第 13 行
“CREATE TRIGGER”必须是查询批处理中的第一条语句。
消息 102,第 15 级,状态 1,第 51 行
'GO' 附近的语法不正确。

谢谢...

【问题讨论】:

    标签: sql-server tsql sql-server-express


    【解决方案1】:

    我遇到了同样的错误,我是如何解决这个问题的

    create or alter procedure mypro
    @msg varchar(20)
    as 
        print(@msg)
    go;
    exec mypro @msg='fft';
    

    输出Incorrect syntax near 'go'

        Started executing query at Line 1   
        Msg 102, Level 15, State 1, Procedure mypro, Line 6
        Incorrect syntax near 'go'. 
    

    删除 ; 后它会起作用。

    create or alter procedure mypro
    @msg varchar(20)
    as 
        print(@msg)
    go;
    exec mypro @msg='fft';
    
    [12:17:59 pm]   Started executing query at Line 1
        Commands completed successfully.
    [12:17:59 pm]   Started executing query at Line 7
        fft
        Total execution time: 00:00:00.062  
    

    【讨论】:

      【解决方案2】:

      1) EXEC[UTE] 只能执行 T-SQL 语句。

      GOis not T-SQL statement

      GO 不是 Transact-SQL 语句;这是一个被认可的命令 sqlcmd 和 osql 实用程序以及 SQL Server Management Studio 代码 编辑。 SQL Server 实用程序将 GO 解释为它们应该 将当前批次的 Transact-SQL 语句发送到 SQL 服务器。

      2) 你可以替换

           SET @SQL = '
      --Drop Trigger
      BEGIN TRY
           DROP TRIGGER [dbo].[TR_' + @TableName + '_Audit]
      END TRY
      BEGIN CATCH
      END CATCH
      GO
      
      --Create Trigger
      CREATE TRIGGER [dbo].[TR_' + @TableName + '_Audit]
      

      DECLARE @TriggerName SYSNAME;
      SET @TriggerName = 'TR_' + @TableName + '_Audit';
      
      IF EXISTS (
          SELECT  *
          FROM    sys.triggers 
          WHERE   parent_id = OBJECT_ID(@TableName)
          AND     name = @TriggerName
      )
      BEGIN
           SET @SQL = N'DROP TRIGGER [dbo].' + QUOTENAME(@TriggerName);
           EXEC(@SQL);
      END
      
          SET @SQL = '
      --Create Trigger
      CREATE TRIGGER [dbo].[TR_' + @TableName + '_Audit]
      

      或(更好)

      DECLARE @TriggerName SYSNAME;
      SET @TriggerName = 'TR_' + @TableName + '_Audit';
      
      IF NOT EXISTS (
          SELECT  *
          FROM    sys.triggers 
          WHERE   parent_id = OBJECT_ID(@TableName)
          AND     name = @TriggerName
      )
      BEGIN
           SET @SQL = N'CREATE TRIGGER [dbo].' + QUOTENAME(@TriggerName) + 'ON ' + @TableName + ' AFTER INSERT, UPDATE, DELETE AS BEGIN SELECT NULL END';
           EXEC(@SQL);
      END
      
          SET @SQL = '
      --Alter Trigger
      ALTER TRIGGER [dbo].[TR_' + @TableName + '_Audit]
      

      注意:对象的名称应为NVARCHAR(128)SYSNAME

      【讨论】:

        【解决方案3】:

        错误说明了问题到底是什么。您正在创建一个动态 sql 语句,由 EXEC 语句一次性运行。 GO 是用于命令行界面或 SSMS 的批处理分隔符。它将多个语句分开分别执行。因此,您不能在要由EXECsp_executesql 执行的查询语句中包含GO。 只需删除 GO 语句,或创建两个查询以由两个 EXEC 语句运行。

        【讨论】:

          【解决方案4】:

          您必须在单个exec() 命令中执行命令的每个部分。

          试试这个:

          CREATE PROCEDURE sp_CreateDataChangedTrigger
              -- Add the parameters for the stored procedure here
              @TableName varchar(255), 
              @TableKey  varchar(255),
              @Debug     bit=1
          AS
          BEGIN
              -- SET NOCOUNT ON added to prevent extra result sets from
              -- interfering with SELECT statements.
              SET NOCOUNT ON;
          
               DECLARE @SQLPart1 varchar(max);
               DECLARE @SQLPart2 varchar(max);
          
               SET @SQLPart1 = '
          --Drop Trigger
          BEGIN TRY
               DROP TRIGGER [dbo].[TR_' + @TableName + '_Audit]
          END TRY
          BEGIN CATCH
          END CATCH
          '
          
          SET @SQLPart2 = '
          --Create Trigger
          CREATE TRIGGER [dbo].[TR_' + @TableName + '_Audit]
               ON [dbo].[' + @TableName + ']
               AFTER INSERT, UPDATE, DELETE
          AS
          BEGIN
               SET NOCOUNT ON
               DECLARE @event_type [char]
          
               --Get Event Type
               IF EXISTS(SELECT * FROM INSERTED)
               IF EXISTS(SELECT * FROM DELETED)
                    SELECT @event_type = ''U''
               ELSE
                    SELECT @event_type = ''I''
               ELSE
               IF EXISTS(SELECT * FROM deleted)
                    SELECT @event_type = ''D''
               ELSE
               --no rows affected - cannot determine event
                    SELECT @event_type = ''K''
          
               IF @event_type IN (''I'',''U'') BEGIN
                    DECLARE @CurrentUserID INT;
                    SELECT  @CurrentUserID = u.UserID
                    FROM    [dbo].[dim_Users] u
                    WHERE   u.[Username] = dbo.udfUserName()
          
                    UPDATE  t
                    SET     DateModified = GETDATE(),
                            WhoModifiedID = @CurrentUserID
                    FROM    INSERTED e
                    JOIN    [dbo].[' + @TableName + '] t ON e.[' + @TableKey + '] = t.[' + @TableKey + ']
               END
          
               IF @event_type = ''D'' BEGIN
                    no_op:  --Nothing for now
               END
          END
          ';
          
               IF @Debug=1 BEGIN
                    set nocount on;
                    print @SQLPart1;
                    print @SQLPart2;
               END
               ELSE BEGIN
                    exec(@SQLPart1);
                    exec(@SQLPart2);
               END    
          END
          GO
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-23
            • 1970-01-01
            • 1970-01-01
            • 2015-02-02
            相关资源
            最近更新 更多