GO 在 EXEC 中使用时会导致错误:“'GO' 附近的语法不正确。”
Posted
技术标签:
【中文标题】GO 在 EXEC 中使用时会导致错误:“\'GO\' 附近的语法不正确。”【英文标题】: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' 附近的语法不正确。
谢谢...
【问题讨论】:
【参考方案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 语句。
GO
is 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 的批处理分隔符。它将多个语句分开分别执行。因此,您不能在要由EXEC
或sp_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
【讨论】:
以上是关于GO 在 EXEC 中使用时会导致错误:“'GO' 附近的语法不正确。”的主要内容,如果未能解决你的问题,请参考以下文章
Raspberry-pi docker 错误:standard_init_linux.go:178:exec 用户进程导致“exec 格式错误”
Docker buildx 与 Apple M1 Silicon 上的节点应用程序 -standard_init_linux.go:211:exec 用户进程导致“exec 格式错误”
standard_init_linux.go:211:exec 用户进程导致“没有这样的文件或目录”?
standard_init_linux.go:219: exec 用户进程导致:没有这样的文件或目录 - docker 问题