【问题标题】:Return number of rows affected with multiple queries返回受多个查询影响的行数
【发布时间】:2016-06-19 03:04:18
【问题描述】:

我正在 SQL Server 中编写一些动态 SQL。有几个查询合并为一个。第一个查询选择数据,第二个删除,第三个插入,最后一个删除临时表:

SET @completeSQL = @tempProdSQL + @deleteSQL + @insertSQL + ' DROP TABLE #tempProd'

PRINT(@completeSQL)

EXEC sp_ExecuteSQL @completeSQL

SET @archiveSize = @@ROWCOUNT

我知道我可以使用@@Rowcount,但我得到的值为 0。我相信这是因为最后一个命令是删除表。

有没有办法让@tempProdSQL 命令之后的行受到影响?如果会影响性能,我宁愿不分离执行。

【问题讨论】:

  • @@rowcount 仅返回受先前执行语句影响的行。换句话说,你是对的,删除表会清除插入行的@@rowcount。但是,您的查询可能仍然存在问题。即使您删除了 drop table 语句,@@rowcount 也只会返回受插入影响的行数。所以——如果你想得到@@rowcount 的总积累量,你需要想出一种不同的方法。
  • 可以使用sp_executesql来获取值,但是这样做会很麻烦。这将涉及调用 sp_executesql 中的每个部分,所有部分都包含在另一个 sp_executesql 中,并从@tempProdSQL 向下传递行数。这会很丑,Yobik 是对的——你可能想在这里重新考虑设计。
  • 另外,在这种情况下,我不会关心性能。 rowcount 的缓存无论如何都会发生,因此您不会通过尝试将其全部放入一个语句中来节省很多东西。

标签: sql sql-server tsql


【解决方案1】:

说明:

sp_executesql 的文档中,有一个“备注”部分是这样说的:

sp_executesql 在批处理方面与 EXECUTE 具有相同的行为, 名称的范围和数据库上下文。 Transact-SQL 语句 sp_executesql stmt 参数中的或批处理直到 sp_executesql 语句被执行。那么stmt的内容就是 作为与执行分开的执行计划编译和执行 调用 sp_executesql 的批处理计划。 sp_executesql 批处理 不能引用在调用的批处理中声明的变量 sp_executesql。 sp_executesql 批处理中的本地游标或变量 对调用 sp_executesql 的批处理不可见。改变在 数据库上下文仅持续到 sp_executesql 语句的末尾。

另一种说法是,因为动态 SQL 直到运行时才被编译,所以它被视为一个单独的批处理,并且在构建/执行它的过程之外有自己的上下文。

如果您利用sp_executesql 的附加参数,即@params@param1,您可以在动态SQL 语句中找到@@row_count,并将该值传递回主批处理/上下文。

解决方案:

编辑:将 @@rowcount 检查移到动态 SQL 的 @tempProdSQL 之后。

declare @row_cnt int --add this to your procedure's variables

set @completeSQL = @tempProdSQL + ' set @row_cnt_dyn = @@rowcount ' + @deleteSQL + @insertSQL + ' DROP TABLE #tempProd' 

print (@completeSQL)
exec sp_executesql @completeSQL
        , N'@row_cnt_dyn int out' --establishing the param in the dynamic sql batch
        , @row_cnt_dyn = @row_cnt out --this is getting the value out of the dynamic batch into the main batch

set @archiveSize = @row_cnt

【讨论】:

  • drop table之后会返回什么?
  • @IvanStarostin 在drop table 之后,@@rowcount 将返回 0。根据 OP 的问题,您的问题使我意识到 @@rowcount 在错误的位置。根据问题将其移至@tempProdSQL 之后。这将返回请求的影响行数。谢谢!
【解决方案2】:

您可以在@tempProdSQL 之后立即捕获@@rowcount 的值,并使用输出参数将其返回到外部上下文:

SET @completeSQL = @tempProdSQL + '; SET @archiveSize1 = @@ROWCOUNT; ' + @deleteSQL + @insertSQL + ' DROP TABLE #tempProd'

PRINT(@completeSQL)

EXEC sp_executesql @completeSQL, N'@archiveSize1 INT OUTPUT', @archiveSize1 = @archiveSize OUTPUT

SELECT '@archiveSize:', @archiveSize

【讨论】:

    猜你喜欢
    • 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
    相关资源
    最近更新 更多