SQL中exec的微妙之处
Posted
技术标签:
【中文标题】SQL中exec的微妙之处【英文标题】:Subtleties of exec in TSQL 【发布时间】:2013-03-27 07:22:52 【问题描述】:这个存储过程
CREATE PROC GetPage(@blockNumber int, @blockSize int = 40, @query varchar(1000))
AS
DECLARE @a int = @blockNumber * @blockSize;
DECLARE @b int = @a + @blockSize - 1;
DECLARE @fromPos int = PATINDEX('% FROM %', @query);
DECLARE @from varchar(1000) = SUBSTRING(@query, @fromPos, 1000);
DECLARE @select varchar(1000) = SUBSTRING(@query, 1, @fromPos);
DECLARE @SQL varchar(1000) =
'select *, ROW_NUMBER() over (order by ONE) R INTO #FOO FROM ('
+@SELECT+',1 ONE'+@from+') T';
EXEC @SQL;
SELECT * FROM FOO WHERE RN BETWEEN @a AND @b;
DECLARE @C INT = (SELECT COUNT(*) FROM #FOO);
DROP TABLE #FOO
RETURN @C;
当通过SELECT * FROM ASSET
时生成这个SQL
select *, ROW_NUMBER() over (order by ONE) R INTO #FOO
FROM (select * ,1 ONE from asset) T
当我从 SQL Server Management Studio 执行此操作时,如下所示:
exec('select *, ROW_NUMBER() over (order by ONE) R INTO #FOO FROM (select * ,1 ONE from asset) T')
它按预期创建表#FOO。
但是,当存储过程执行时:
exec getpage 5,10,'select * from asset'
我收到此错误
消息 2812,级别 16,状态 62,过程 GetPage,第 12 行 找不到存储过程 'select *, ROW_NUMBER() over (order by ONE) R INTO FOO FROM (select * ,1 ONE from assets) T'。 消息 208,级别 16,状态 1,过程 GetPage,第 14 行 无效的对象名称“#FOO”。
我认为第二条消息仅仅是第一个错误的结果。有谁知道为什么exec
语句在存储过程中的行为不同?
【问题讨论】:
【参考方案1】:在你的 exec 中使用括号
EXEC (@SQL);
EXECUTE (Transact-SQL)
没有括号,你使用的是这个:
执行存储过程或函数 [ 执行 |执行 ] [@return_status =] 模块名称 [ ; 编号 ] | @module_name_var [ [ @parameter = ] 值 | @变量[输出] | [ 默认 ] ] [ ,...n ] [ 与 [ ,...n ] ] [;]在需要括号的地方你想要这个。
执行一个字符串 执行 |执行 ( @string_variable | [ N ]'tsql_string' [ + ...n ] ) [作为登录|用户 ='名称'] [;]【讨论】:
碰巧我自己解决了这个问题,但这只是让我确定你提供了一个正确的答案。荣誉是你的。谢谢你的帮忙。你会认为他们会从参数类型推断出来,就像 .NET 方法一样...... @mikael-eriksson - 无论如何要使用括号,但将 proc 的输出分配给类似 @a = exec (@sql) 的变量以上是关于SQL中exec的微妙之处的主要内容,如果未能解决你的问题,请参考以下文章
Android Sqlite 数据库 db.exec() 在 SQL 文本中返回语法错误