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的微妙之处的主要内容,如果未能解决你的问题,请参考以下文章

SQL命令use、go、exec的作用是啥?

Android Sqlite 数据库 db.exec() 在 SQL 文本中返回语法错误

在存储过程中使用带有 exec @sql 的临时表

在 T-SQL 语句任务中运行 EXEC 过程时出错

SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别

Oracle中执行存储过程call和exec区别