【问题标题】:SQL Server : dymanic SQL error: 'CREATE VIEW' must be the first statement in a query batchSQL Server:动态 SQL 错误:“CREATE VIEW”必须是查询批处理中的第一条语句
【发布时间】:2016-08-25 12:59:19
【问题描述】:

我用动态 SQL 编写了一个存储过程,当我调用它时会引发错误:

IF OBJECT_ID('[dbo].[find_most_frequent]') IS NOT NULL
  DROP PROCEDURE [dbo].[find_most_frequent]
GO

CREATE PROCEDURE [dbo].[find_most_frequent] 
        @table_in VARCHAR(100),
        @table_out VARCHAR(100),
        @col_group VARCHAR(100),
        @col_2 VARCHAR(100) 
AS
BEGIN 
    DECLARE @sql NVARCHAR(4000);

    SET @sql =
    --start of code
    'USE CTR
GO

IF OBJECT_ID(N''[dbo].[two_columns]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[two_columns];

IF OBJECT_ID(N''[dbo].[count_in_group]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[count_in_group];

IF OBJECT_ID(N''[dbo].[rank_in_group]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[rank_in_group];

IF OBJECT_ID(N''[dbo].[most_frequent_in_group]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[most_frequent_in_group];
GO

CREATE VIEW [dbo].[two_columns] AS
SELECT ' +
        @col_group +
        ' ,' + @col_2 +
    ' FROM ' + @table_in +
'
GO

CREATE VIEW [dbo].[count_in_group] AS
SELECT  DISTINCT
        *
        ,COUNT(*) OVER(PARTITION BY ' + @col_group + ', ' + @col_2 + ') AS freq
    FROM [dbo].[two_columns]
GO  

CREATE VIEW [dbo].[rank_in_group] AS
SELECT  *
        ,ROW_NUMBER() OVER (PARTITION BY ' + @col_group + ' ORDER BY freq DESC) AS rank_in_group
    FROM [dbo].[count_in_group]
GO

CREATE VIEW [dbo].[most_frequent_in_group] AS
SELECT *
    FROM [dbo].[rank_in_group]
    WHERE rank_in_group = 1
GO

SELECT *
    INTO ' + @table_out + 
    ' FROM [dbo].[most_frequent_in_group]
GO'
--end of code    
    print @sql
    EXEC SP_EXECUTESQL @sql
END 
GO

--call it
EXEC [dbo].[find_most_frequent]
        @table_in = '[dbo].[table_1]'
        ,@table_out = '[dbo].[table_out]'
        ,@col_group = '[col_A]'
        ,@col_2 = '[col_B]' 
GO

错误:

消息 102,第 15 级,状态 1,第 81 行
“GO”附近的语法不正确。
消息 102,第 15 级,状态 1,第 91 行
“GO”附近的语法不正确。
消息 111,第 15 级,状态 1,第 93 行
“CREATE VIEW”必须是查询批处理中的第一条语句。
消息 111,第 15 级,状态 1,第 97 行
“CREATE VIEW”必须是查询批处理中的第一条语句。
消息 111,第 15 级,状态 1,第 104 行
“CREATE VIEW”必须是查询批处理中的第一条语句。
消息 111,第 15 级,状态 1,第 110 行
“CREATE VIEW”必须是查询批处理中的第一条语句。
消息 102,第 15 级,状态 1,第 114 行
'GO' 附近的语法不正确。

行号没用,因为它们是我的代码末尾之后的行...

在程序中我打印了@sql 来看看。我复制打印的代码并将其粘贴到另一个查询中,它起作用了。 - 所以我现在完全不知道如何调试它....

USE CTR
GO

IF OBJECT_ID(N'[dbo].[two_columns]', N'V') IS NOT NULL
    DROP VIEW [dbo].[two_columns];

IF OBJECT_ID(N'[dbo].[count_in_group]', N'V') IS NOT NULL
    DROP VIEW [dbo].[count_in_group];

IF OBJECT_ID(N'[dbo].[rank_in_group]', N'V') IS NOT NULL
    DROP VIEW [dbo].[rank_in_group];

IF OBJECT_ID(N'[dbo].[most_frequent_in_group]', N'V') IS NOT NULL
    DROP VIEW [dbo].[most_frequent_in_group];
GO

CREATE VIEW [dbo].[two_columns] AS
SELECT [hash_vcc] ,[legal_name] FROM [dbo].[ctr_vendor_pay]
GO

CREATE VIEW [dbo].[count_in_group] AS
SELECT  DISTINCT
        *
        ,COUNT(*) OVER(PARTITION BY [hash_vcc], [legal_name]) AS freq
    FROM [dbo].[two_columns]
GO  

CREATE VIEW [dbo].[rank_in_group] AS
SELECT  *
        ,ROW_NUMBER() OVER (PARTITION BY [hash_vcc] ORDER BY freq DESC) AS rank_in_group
    FROM [dbo].[count_in_group]
GO

CREATE VIEW [dbo].[most_frequent_in_group] AS
SELECT *
    FROM [dbo].[rank_in_group]
    WHERE rank_in_group = 1
GO

SELECT *
    INTO [dbo].[hashvcc_2_legalname] FROM [dbo].[most_frequent_in_group]
GO

有人可以帮忙吗?任何帮助表示赞赏。谢谢

更新

我将每个CREATE VIEW 拆分为不同的字符串,并分别执行它们。 - 使用BEGIN END 包裹每个CREATE VIEW 不起作用。

现在这块仍然抛出错误:

CREATE VIEW [dbo].[most_frequent_in_group] AS
SELECT *
    FROM [dbo].[rank_in_group]
    WHERE rank_in_group = 1

SELECT *
    INTO [dbo].[hashvcc_2_legalname]
    FROM [dbo].[most_frequent_in_group]

错误:

关键字“SELECT”附近的语法不正确。

当我分别运行 CREATE VIEWSELECT 时它可以工作。

得到答案:VIEW 必须是批处理中的唯一语句 - 感谢@ZLK

【问题讨论】:

  • 不幸的是,由于GO 实际上不是 T-SQL(请参阅此处的备注:msdn.microsoft.com/en-us/library/ms188037.aspx),您将不得不考虑另一种选择,例如分解每个部分并分别执行它们。跨度>
  • 谢谢@ZLK! BEGIN END 有效吗?
  • 在动态sql中?是的...但不适用于创建视图和其他需要在批处理开始时进行的操作。
  • 我明白了。是的,我测试了 BEGIN END 并没有修复 must be the first statement in a query batch. 的错误
  • 嗨@ZLK 很抱歉再次打扰。你能看看OP中的更新吗?为什么SELECT 不能关注CREATE VIEW xxx AS SELECT .. FROM ...?谢谢

标签: sql-server dynamic-sql


【解决方案1】:

关于GO

GO 不是 Transact-SQL 语句;这是一个被认可的命令 sqlcmd 和 osql 实用程序以及 SQL Server Management Studio 代码 编辑。

将您的查询拆分为单独的请求:

EXEC sp_executesql N'
USE CTR

IF OBJECT_ID(N''[dbo].[two_columns]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[two_columns];
IF OBJECT_ID(N''[dbo].[count_in_group]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[count_in_group];
IF OBJECT_ID(N''[dbo].[rank_in_group]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[rank_in_group];
    IF OBJECT_ID(N''[dbo].[most_frequent_in_group]'', N''V'') IS NOT NULL
    DROP VIEW [dbo].[most_frequent_in_group];'

EXEC sp_executesql N'
CREATE VIEW [dbo].[two_columns] AS
SELECT [hash_vcc] ,[legal_name] FROM [dbo].[ctr_vendor_pay]'

...

等等。

【讨论】:

  • 我明白了。谢谢@Backs! BEGIN END 有效吗?字符串前的 N 是必要的吗?谢谢-
  • @YZhang BEGINEND 是有效的 TSQL 语法。 N 表示字符串是 unicode。存储过程 sp_executesql 仅适用于 unicode
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多