【问题标题】:Create a temporary table dynamically from calling an stored procedure通过调用存储过程动态创建临时表
【发布时间】:2020-12-26 13:00:23
【问题描述】:

我想通过调用存储过程来创建一个临时表,如下所示

Select * 
into #temp1 
from 
    exec sp1;

select * 
into #temp1 
from sys.dm_exec_describe_first_result_set_for_object(object_id('dbo.sp1'), 1) 

获取第二个结果集

我知道稍后选项仅用于获取第一个结果集。但我想获取第 n 个结果集并直接从中创建一个临时表,而不定义临时表。

我的最终目标是使用 tSQLt 测试用例将来自 SP 的第二个结果集的列数据类型与我预期的表模式进行比较。所以定义实际表和预期表没有意义。每次都会过去。

【问题讨论】:

  • "我们如何动态创建临时表......而不定义临时表。" ?????
  • 感谢@SMor 在上面的链接中,它建议使用 SQLCLR。我还没有深入研究它。但它肯定说要在 SQL 服务器窗口之外编码。我的最终目标是编写一个 tSQLt 测试用例,我将在其中定义一个临时表定义并比较我的 proc 的第二个结果集的模式。所以在这种情况下,我无法定义临时表。否则测试用例没有意义。
  • T-SQL 本身不支持从存储过程中分离数据集。听起来你应该有 2 个程序。
  • 也许更好的问题是为什么您(或您组织中的某个人)决定编写存储过程来生成多个结果集。这首先是设计/编写“工作单元”的一种有问题的方法 - 显然 tsql 不是为了处理而设计的。

标签: sql sql-server tsqlt


【解决方案1】:

我的最终目标是比较第二个结果集的列数据类型 来自使用 tSQLt 测试用例的具有我预期表架构的 SP。

将返回第二个结果集的代码重构到自己的 proc 中会使测试更容易,但它是可行的。

假设您的测试过程如下所示

CREATE PROCEDURE dbo.ProcedureUnderTest
AS
BEGIN

SELECT 1 AS ResultSet1Col1

SELECT 2 AS ResultSet2Col1, 'Foo' AS ResultSet2Col2

END

您可以通过在tSQLt.AssertResultSetsHaveSameMetaData 的执行中嵌套对tSQLt.ResultSetFilter 的调用来实现验证第二个结果集格式的预期目标

CREATE TABLE #expected
(
   ResultSet2Col1 INT NULL,
   ResultSet2Col2 VARCHAR(3) NULL
)


EXEC tSQLt.AssertResultSetsHaveSameMetaData
  @expectedCommand = 'SELECT * FROM #expected',
  @actualCommand = 'EXEC tSQLt.ResultSetFilter 2, ''EXEC dbo.ProcedureUnderTest'';' 

【讨论】:

    【解决方案2】:

    试试这个方法

    SELECT * INTO #temp1 FROM OPENROWSET('SQLNCLI','Server=YourServer;Trusted_Connection=yes;','exec DBName.Schema.sp1') AS a
    

    以下是有限的范围,因为“#Temp1”不能在它之外使用!

    Declare @Table VARCHAR(MAX)=''
    select @Table = @Table + ',' + [Name] + ' ' + system_type_name  from sys.dm_exec_describe_first_result_set_for_object(object_id('dbo.sp1'), 1) 
    set @Table = stuff(@Table,1,1,'')
    Exec('Create Table #temp1(' + @Table + ')
    Insert #temp1
    Exec dbo.sp1
    ')
    

    或者

    以下应与“全局临时表”一起使用

    Declare @Table VARCHAR(MAX)=''
    select @Table = @Table + ',' + [Name] + ' ' + system_type_name  from sys.dm_exec_describe_first_result_set_for_object(object_id('dbo.sp1'), 1) 
    set @Table = stuff(@Table,1,1,'')
    Exec('Create Table ##temp1(' + @Table + ')')
    
    Insert ##temp1
    Exec dbo.sp1
    
    drop table ##temp1
    

    【讨论】:

    • 其实我也看到了这个选项,但是出于安全原因,我们的组织服务器上没有启用它。
    • 建议另外两个选项。但是,也要根据限制和性能角度来决定自己
    • 但是 sys.dm_exec_describe_first_result_set_for_object 只能用于第一个结果集。我想从 sp1 访问第二个结果集。
    猜你喜欢
    • 1970-01-01
    • 2018-03-16
    • 1970-01-01
    • 2010-09-12
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    相关资源
    最近更新 更多