【发布时间】: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 VIEW 和 SELECT 时它可以工作。
得到答案: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 ...?谢谢