【问题标题】:Insert results of a stored procedure into a temporary table将存储过程的结果插入到临时表中
【发布时间】:2018-11-16 11:14:30
【问题描述】:

我该怎么做SELECT * INTO [temp table] FROM [stored procedure]?不是FROM [Table],也没有定义[temp table]

SelectBusinessLinetmpBusLine 的所有数据都可以正常工作。

select *
into tmpBusLine
from BusinessLine

我也在尝试相同的方法,但使用返回数据的stored procedure 并不完全相同。

select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'

输出信息:

消息 156,级别 15,状态 1,行 2 关键字附近的语法不正确 '执行'。

我已经阅读了几个创建与输出存储过程具有相同结构的临时表的示例,它工作正常,但最好不提供任何列。

【问题讨论】:

  • 使用 SELECT * INTO [TABLE NAME] 您确实知道列,因为它们是从原始表中复制的。如果我要对存储过程做同样的事情,这正是我想要的。
  • 只想指出“select * into tmpBusLine”会创建一个永久表。您可能想要“选择 * 进入 #tmpBusLine”。我确定原始发帖人已经发现了这一点,但它可能会帮助其他找到这篇文章的人,因为它是当前搜索“选择进入临时表”的最佳结果
  • 我不知道这是否已经解决,但您收到错误的原因是因为 from 关键字。
  • 微软需要添加SELECT * INTO FROM EXEC!请!

标签: sql sql-server sql-server-2005 tsql stored-procedures


【解决方案1】:

您可以为此使用OPENROWSET。看一看。我还包含了 sp_configure 代码以启用 Ad Hoc 分布式查询,以防它尚未启用。

CREATE PROC getBusinessLineHistory
AS
BEGIN
    SELECT * FROM sys.databases
END
GO

sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO

SELECT * INTO #MyTempTable FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC getBusinessLineHistory')

SELECT * FROM #MyTempTable

【讨论】:

  • 这是正确的做法。 OPENROWSET 几乎是将存储过程的结果视为表表达式的唯一方法。
  • 这似乎有点麻烦,只是插入到表格中。很多配置要做。此外,当我尝试它时,我得到“消息 7357,级别 16,状态 2,第 1 行无法处理对象“EXEC GetPartyAnalysisData 146”。链接服务器“(null)”的 OLE DB 提供程序“SQLNCLI”表明该对象有没有列或当前用户对该对象没有权限。”所以你需要设置一个链接服务器...
  • 您不需要链接服务器,但您需要正确获取连接字符串...并且还要指定存储过程的完整路径,包括数据库名称和 sp 的所有者。
  • 哎呀!对同一服务器的引用?可恶的。绝对比手动创建临时表更像一个 hack
  • 我同意这是一个 hack,应该避免,除非你的背靠墙。将 sp 更改为函数可能是一个更好的角度。恕我直言。
【解决方案2】:

如果您想在不首先声明临时表的情况下执行此操作,您可以尝试创建一个用户定义的函数而不是 stored procedure,并让该用户定义的函数返回一个表。或者,如果您想使用存储过程,请尝试以下操作:

CREATE TABLE #tmpBus
(
   COL1 INT,
   COL2 INT
)

INSERT INTO #tmpBus
Exec SpGetRecords 'Params'

【讨论】:

  • 我认为关键是无需显式声明即可生成架构。
  • 我很想知道这与上述@Aaron Alton 的解决方案有什么区别。这个看起来要简单得多,但我不确定其他任何含义。
  • 这会起作用,但是如果您向 SpGetRecords 存储过程添加额外的列,这将会崩溃。
  • 每个调用堆栈只能获得一个 INSERT INTO EXEC。 SpGetRecords 和它调用的任何其他过程可能不会在自己的代码中使用此策略。这可能会让 SpGetRecords 的维护者感到惊讶。
  • 这根本不能回答问题,我不明白为什么它如此受欢迎? OP 明确声明“不定义 [temp table]”,并且您的第一行有一个 create temp table 语句。
【解决方案3】:

在 SQL Server 2005 中,您可以使用INSERT INTO ... EXEC 将存储过程的结果插入到表中。来自MSDN's INSERT documentation(实际上是针对 SQL Server 2000):

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales

【讨论】:

  • 这需要预先定义 authors_sales。我试图避免这种情况。谢谢。
  • 我也是这么想的。即时插入到 tmp 表中非常有用,但如果您需要知道从存储过程返回的数据集结构,则不是那么有用。谢谢你的帮助。
  • 要使用相同的schema,可以复制如下:select top 0 * into tempTable from realTable (stackoverflow.com/a/9206463/73794)
  • @EvenMien 当我看到你的评论时我一时兴奋......但遗憾的是,只有当你的 proc 的结果实际上反映了一张真实的桌子时,这才有效:(
【解决方案4】:

这是对您的问题稍作修改的版本的答案。如果您可以放弃对用户定义函数使用存储过程,则可以使用内联表值用户定义函数。这本质上是一个存储过程(将接受参数),它返回一个表作为结果集;因此可以很好地放置一个 INTO 语句。

这里有一个很好的quick article 和其他用户定义的函数。如果您仍然需要存储过程,则可以使用存储过程包装内联表值用户定义函数。存储过程仅在从内联表值用户定义函数调用 select * 时传递参数。

因此,例如,您将有一个内联表值用户定义函数来获取特定区域的客户列表:

CREATE FUNCTION CustomersByRegion 
(  
    @RegionID int  
)
RETURNS TABLE 
AS
RETURN 
  SELECT *
  FROM customers
  WHERE RegionID = @RegionID
GO

然后你可以调用这个函数来得到你的结果:

SELECT * FROM CustomersbyRegion(1)

或者做一个SELECT INTO:

SELECT * INTO CustList FROM CustomersbyRegion(1)

如果你还需要一个存储过程,那么把函数包装成这样:

CREATE PROCEDURE uspCustomersByRegion 
(  
    @regionID int  
)
AS
BEGIN
     SELECT * FROM CustomersbyRegion(@regionID);
END
GO

我认为这是获得所需结果的最“简单”的方法。它使用现有的功能,因为它们的使用目的是没有额外的复杂性。通过将内联表值用户定义函数嵌套在存储过程中,您可以通过两种方式访问​​该功能。加!对于实际的 SQL 代码,您只有一个维护点。

建议使用 OPENROWSET,但这不是 OPENROWSET 函数的用途(来自联机丛书):

包括所有连接信息 访问远程数据所需的 来自 OLE DB 数据源。这 方法是访问的替代方法 链接服务器中的表,并且是 一次性、特殊的连接方法 并使用 OLE 访问远程数据 D B。对于更频繁的参考 OLE DB 数据源,使用链接 代替服务器。

使用 OPENROWSET 可以完成工作,但会产生一些额外的开销来打开本地连接和编组数据。它也可能不是在所有情况下都是一个选项,因为它需要一个特别的查询权限,这会带来安全风险,因此可能是不希望的。此外,OPENROWSET 方法将排除使用返回多个结果集的存储过程。在单个存储过程中包装多个内联表值用户定义函数可以实现这一点。

【讨论】:

  • +1 表值函数是一个合适的解决方案。我们应该注意一些小缺点:表值函数是一个额外的数据库对象,可能需要对其授予权限。
  • 喜欢这个解决方案。我遇到的一个小问题是,我的表不能按存储过程中的位置排序。哦,那我去整理一下
  • 还有一个障碍 - “无法从函数内访问临时表”
  • 最初的问题是我们如何创建一个带有 sp 的结果的临时表。这是一个很好的模式,但没有解决这个问题
  • greg,我回答的第一行指出“这是对您问题的略微修改版本的回答。”您的评论是多余的。
【解决方案5】:
Select @@ServerName
EXEC sp_serveroption @@ServerName, 'DATA ACCESS', TRUE

SELECT  *
INTO    #tmpTable
FROM    OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')

【讨论】:

  • 获取“Msg 208, Level 16, State 1, Line 1 Invalid object name 'tmpBusLine'(可能是因为它没有预先定义)。
  • @Ferds:抱歉,一开始没有理解您的要求。用另一个解决方案更新。
  • 很好的解决方案。需要注意的是,您需要在服务器上启用“数据访问”:EXEC sp_serveroption 'TheServerName', 'DATA ACCESS', TRUE
  • 您还需要允许远程访问服务器。这将产生安全后果。
  • 如果目标存储过程使用临时表,这将不起作用
【解决方案6】:

最简单的解决方案:

CREATE TABLE #temp (...);

INSERT INTO #temp
EXEC [sproc];

如果您不知道架构,那么您可以执行以下操作。 请 请注意,此方法存在严重的安全风险。

SELECT * 
INTO #temp
FROM OPENROWSET('SQLNCLI', 
                'Server=localhost;Trusted_Connection=yes;', 
                'EXEC [db].[schema].[sproc]')

【讨论】:

  • 如果我不知道返回结果集的列那么???我的意思是列可能会有所不同。那么如何将结果插入临时表???
  • 您可以使用 OPENQUERY,但不推荐使用,因为它存在安全漏洞。
  • “如果我不知道返回结果集的列”那么你不能在你的逻辑中使用它。如果您不知道数据是什么,您将如何使用这些数据?
  • @AdriaanDavel 我同意您的观点,您应该始终了解您的数据(最佳实践),但是他可能会说,有时存储过程会返回动态列而您并不总是知道架构会是什么样子。在这种情况下,您可以使用 OPENROWSET 动态插入和创建表。但是,这样做存在明显的安全风险......
  • @nurettin 有时您不知道存储过程将返回什么。在那种情况下会发生什么?你怎么能创建一个临时表(当你不知道存储过程将返回什么时)并从存储过程中插入?
【解决方案7】:

当存储过程返回很多列并且您不想手动“创建”一个临时表来保存结果时,我发现最简单的方法是进入存储过程并添加一个“into”在最后一个 select 语句中添加 1=0 到 where 子句。

运行一次存储过程,然后返回并删除您刚刚添加的 SQL 代码。现在,您将有一个与存储过程的结果匹配的空表。您可以为临时表“将表作为创建脚本”,也可以直接插入到该表中。

【讨论】:

  • +1,很好的建议。您甚至可以在存储过程中添加一个名为@TableCreate 的快速可选变量,或者类似的东西,当不为空时执行上述步骤。不需要更改存储过程,一旦设置完成。
  • @dotjoe 你做一个SELECT INTO 一个临时表并做一个从临时表创建的脚本表吗?临时表显示在tempdb 中,但我无法右键单击并执行创建脚本。任何帮助表示赞赏。
  • @DotNetDude 你可以select ... into new_table 隐式创建一个实际的表。
  • 然后从空表模式中获取粗略的列定义;用合法的 TABLE_NAME 替换末尾的“...”:declare @s varchar(max)='';select @s=@s+','+COLUMN_NAME+' '+DATA_TYPE+isnull('('+case CHARACTER_MAXIMUM_LENGTH when -1 then 'max' else cast(CHARACTER_MAXIMUM_LENGTH as varchar(10))end+')','')from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='...';select @s
  • 这是最好的解决方案!
【解决方案8】:
declare @temp table
(
    name varchar(255),
    field varchar(255),
    filename varchar(255),
    filegroup varchar(255),
    size varchar(255),
    maxsize varchar(255),
    growth varchar(255),
    usage varchar(255)
);
INSERT @temp  Exec sp_helpfile;
select * from @temp;

【讨论】:

  • 没有解决 OP 原始问题,在没有先定义临时表的情况下进行插入。
  • 这正是我想要的。这允许我在无法控制过程时向结果集添加分页
【解决方案9】:

如果你的存储过程的结果表太复杂而无法手动输入“create table”语句,并且你不能使用OPENQUERY OR OPENROWSET,你可以使用sp_help生成列和数据类型的列表你。获得列列表后,只需对其进行格式化以满足您的需要。

第 1 步:在输出查询中添加“into #temp”(例如“select [...] into #temp from [...]”)。

最简单的方法是直接在 proc 中编辑输出查询。如果您无法更改存储过程,您可以将内容复制到新的查询窗口并在那里修改查询。

第 2 步:在临时表上运行 sp_help。 (例如“exec tempdb..sp_help #temp”)

创建临时表后,对临时表运行 sp_help 以获取列和数据类型的列表,包括 varchar 字段的大小。

第 3 步:将数据列和类型复制到创建表语句中

我有一张 Excel 表格,用于将 sp_help 的输出格式化为“create table”语句。您不需要任何花哨的东西,只需复制并粘贴到您的 SQL 编辑器中即可。使用列名、大小和类型来构造“Create table #x [...]”或“declare @x table [...]”语句,您可以使用它们来插入存储过程的结果。

第 4 步:插入新创建的表中

现在您将获得一个类似于此线程中描述的其他解决方案的查询。

DECLARE @t TABLE 
(
   --these columns were copied from sp_help
   COL1 INT,
   COL2 INT   
)

INSERT INTO @t 
Exec spMyProc 

此技术还可用于将临时表 (#temp) 转换为表变量 (@temp)。虽然这可能比您自己编写 create table 语句要多一些步骤,但它可以防止大型进程中出现诸如拼写错误和数据类型不匹配之类的手动错误。调试错字可能比一开始就编写查询花费更多时间。

【讨论】:

    【解决方案10】:

    您的存储过程是否只检索数据或修改数据?如果仅用于检索,则可以将存储过程转换为函数并使用公用表表达式(CTE)而无需声明,如下所示:

    with temp as (
        select * from dbo.fnFunctionName(10, 20)
    )
    select col1, col2 from temp
    

    但是,任何需要从 CTE 检索的内容都应仅在一个语句中使用。您不能执行 with temp as ... 并在几行 SQL 之后尝试使用它。对于更复杂的查询,您可以在一个语句中包含多个 CTE。

    例如,

    with temp1020 as (
        select id from dbo.fnFunctionName(10, 20)
    ),
    temp2030 as (
        select id from dbo.fnFunctionName(20, 30)
    )
    select * from temp1020 
    where id not in (select id from temp2030)
    

    【讨论】:

    【解决方案11】:

    如果 OPENROWSET 导致您出现问题,则从 2012 年开始还有另一种方法;使用 sys.dm_exec_describe_first_result_set_for_object,如下所述:Retrieve column names and types of a stored procedure?

    首先,创建这个存储过程来为临时表生成 SQL:

    CREATE PROCEDURE dbo.usp_GetStoredProcTableDefinition(
        @ProcedureName  nvarchar(128),
        @TableName      nvarchar(128),
        @SQL            nvarchar(max) OUTPUT
    )
    AS
    SET @SQL = 'CREATE TABLE ' + @tableName + ' ('
    
    SELECT @SQL = @SQL + '['+name +'] '+ system_type_name +''  + ','
            FROM sys.dm_exec_describe_first_result_set_for_object
            (
              OBJECT_ID(@ProcedureName), 
              NULL
            );
    
    --Remove trailing comma
    SET @SQL = SUBSTRING(@SQL,0,LEN(@SQL))    
    SET @SQL =  @SQL +')'
    

    要使用该过程,请按以下方式调用它:

    DECLARE     @SQL    NVARCHAR(MAX)
    
    exec dbo.usp_GetStoredProcTableDefinition
        @ProcedureName='dbo.usp_YourProcedure',
        @TableName='##YourGlobalTempTable',@SQL = @SQL OUTPUT
    
    INSERT INTO ##YourGlobalTempTable
    EXEC    [dbo].usp_YourProcedure
    
    select * from ##YourGlobalTempTable
    

    请注意,我使用的是全局临时表。这是因为使用 EXEC 运行动态 SQL 会创建自己的会话,因此普通临时表将超出任何后续代码的范围。如果全局临时表有问题,您可以使用普通临时表,但任何后续 SQL 都需要是动态的,即也由 EXEC 语句执行。

    【讨论】:

    • 您忘记从@SQL 创建表。
    【解决方案12】:

    Quassnoi 让我走了大部分路,但缺少一件事:

    ****我需要在存储过程中使用参数。****

    OPENQUERY 不允许这种情况发生:

    所以我找到了一种工作系统的方法,也不必使表定义如此死板,并在另一个存储过程中重新定义它(当然要冒险它可能会破坏)!

    是的,您可以通过以下方式动态创建从存储过程返回的表定义 使用带有虚假变量的 OPENQUERY 语句(只要 NO RESULT SET 返回 与具有良好数据的数据集相同的字段数量和位置)。

    创建表后,您可以整天使用 exec 存储过程进入临时表。


    请注意(如上所述)您必须启用数据访问,

    EXEC sp_serveroption 'MYSERVERNAME', 'DATA ACCESS', TRUE
    

    代码:

    declare @locCompanyId varchar(8)
    declare @locDateOne datetime
    declare @locDateTwo datetime
    
    set @locDateOne = '2/11/2010'
    set @locDateTwo = getdate()
    
    --Build temporary table (based on bogus variable values)
    --because we just want the table definition and
    --since openquery does not allow variable definitions...
    --I am going to use bogus variables to get the table defintion.
    
    select * into #tempCoAttendanceRpt20100211
    FROM OPENQUERY(DBASESERVER,
      'EXEC DATABASE.dbo.Proc_MyStoredProc 1,"2/1/2010","2/15/2010 3:00 pm"')
    
    set @locCompanyId = '7753231'
    
    insert into #tempCoAttendanceRpt20100211
    EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo
    
    set @locCompanyId = '9872231'
    
    insert into #tempCoAttendanceRpt20100211
    EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo
    
    select * from #tempCoAttendanceRpt20100211
    drop table #tempCoAttendanceRpt20100211
    

    感谢您最初提供的信息... 是的,当使用来自 另一个存储过程或数据库,是的你也可以使用参数。

    搜索参考标签:

    • SQL 2005 存储过程到临时表

    • 带有存储过程和变量的 openquery 2005

    • 带变量的openquery

    • 在临时表中执行存储过程

    更新:这不适用于临时表,所以我不得不求助于手动创建临时表。

    糟糕的通知:这不适用于临时表http://www.sommarskog.se/share_data.html#OPENQUERY

    参考:接下来就是定义LOCALSERVER。在示例中它可能看起来像一个关键字,但实际上它只是一个名称。这就是你的做法:

    sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                       @provider = 'SQLOLEDB', @datasrc = @@servername
    

    要创建链接服务器,您必须具有 ALTER ANY SERVER 权限,或者是任何固定服务器角色 sysadmin 或 setupadmin 的成员。

    OPENQUERY 打开到 SQL Server 的新连接。这有一些含义:

    您使用 OPENQUERY 调用的过程不能引用在当前连接中创建的临时表。

    新连接有自己的默认数据库(使用 sp_addlinkedserver 定义,默认为 master),因此所有对象规范都必须包含数据库名称。

    如果您有一个打开的事务并且在您调用 OPENQUERY 时持有锁,则被调用的过程无法访问您锁定的内容。也就是说,一不小心就会把自己挡住。

    连接不是免费的,所以会有性能损失。

    【讨论】:

    • 如果您不知道您的服务器名称,请使用SELECT @@SERVERNAME。你也可以使用EXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
    【解决方案13】:

    如果你有幸拥有 SQL 2012 或更高版本,你可以使用dm_exec_describe_first_result_set_for_object

    我刚刚编辑了gotqn提供的sql。谢谢gotqn。

    这将创建一个名称与过程名称相同的全局临时表。临时表可以稍后根据需要使用。只是不要忘记在重新执行之前删除它。

        declare @procname nvarchar(255) = 'myProcedure',
                @sql nvarchar(max) 
    
        set @sql = 'create table ##' + @procname + ' ('
        begin
                select      @sql = @sql + '[' + r.name + '] ' +  r.system_type_name + ','
                from        sys.procedures AS p
                cross apply sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r
                where       p.name = @procname
    
                set @sql = substring(@sql,1,len(@sql)-1) + ')'
                execute (@sql)
                execute('insert ##' + @procname + ' exec ' + @procname)
        end
    

    【讨论】:

    • 太棒了!仅此一句:如果要对内置存储过程执行此操作,请使用 sys.all_objects 而不是 sys.procedures
    • 如果 SP 在其中使用临时表,这也会失败。 (但在你的武器库中将其作为 proc 非常方便)
    【解决方案14】:

    这个存储过程完成了这项工作:

    CREATE PROCEDURE [dbo].[ExecIntoTable]
    (
        @tableName          NVARCHAR(256),
        @storedProcWithParameters   NVARCHAR(MAX)
    )
    AS
    BEGIN
        DECLARE @driver         VARCHAR(10)
        DECLARE @connectionString   NVARCHAR(600)
        DECLARE @sql            NVARCHAR(MAX)
        DECLARE @rowsetSql      NVARCHAR(MAX)
    
        SET @driver = '''SQLNCLI'''
    
        SET @connectionString = 
            '''server=' + 
                CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)) + 
                COALESCE('\' + CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(256)), '') + 
            ';trusted_connection=yes'''
    
        SET @rowsetSql = '''EXEC ' + REPLACE(@storedProcWithParameters, '''', '''''') + ''''
    
        SET @sql = '
    SELECT
        *
    INTO 
        ' + @tableName + ' 
    FROM
        OPENROWSET(' + @driver + ',' + @connectionString + ',' + @rowsetSql + ')'
    
        EXEC (@sql)
    END
    GO
    

    这是对 Insert stored procedure results into table 的轻微修改,因此它确实有效。

    如果您希望它与临时表一起使用,那么您将需要使用 ##GLOBAL 表并在之后删除它。

    【讨论】:

      【解决方案15】:

      为了将存储过程的第一个记录集插入到临时表中,您需要了解以下内容:

      1. 只能将存储过程的第一行集插入到临时表中
      2. 存储过程不得执行动态 T-SQL 语句 (sp_executesql)
      3. 需要先定义临时表的结构

      以上可能看起来是限制,但恕我直言,这完全有道理 - 如果您使用sp_executesql,您可以一次返回两列,一次返回十列,如果您有多个结果集,则不能将它们插入到多个表中好吧 - 您可以在一个 T-SQL 语句中最多插入两个表(使用 OUTPUT 子句并且没有触发器)。

      所以,问题主要是如何在执行EXEC ... INTO ...语句之前定义临时表结构。

      第一个适用于OBJECT_ID,而第二个和第三个也适用于即席查询。我更喜欢使用 DMV 而不是 sp,因为您可以使用 CROSS APPLY 并同时为多个过程构建临时表定义。

      SELECT p.name, r.* 
      FROM sys.procedures AS p
      CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r;
      

      另外,请注意system_type_name 字段,因为它非常有用。它存储列完整定义。例如:

      smalldatetime
      nvarchar(max)
      uniqueidentifier
      nvarchar(1000)
      real
      smalldatetime
      decimal(18,2)
      

      而且大部分情况下都可以直接使用它来创建表定义。

      所以,我认为在大多数情况下(如果存储过程符合某些条件),您可以轻松构建动态语句来解决此类问题(创建临时表,将存储过程结果插入其中,做您需要的数据)。


      请注意,上述对象未能在某些cases 中定义第一个结果集数据,例如在执行动态T-SQL 语句或在存储过程中使用临时表时。

      【讨论】:

      • 对限制的实际观察:如果您必须将某些 sp(我们称之为 SP_LEVEL_0)的输出插入到使用上述方法在另一个 sp(我们称之为 SP_LEVEL_1)中动态创建的临时表中,您不能这样做将此 SP_LEVEL_1 输出到 SP_LEVEL_2 中的另一个临时表的相同技巧
      【解决方案16】:
      1. 我正在使用以下架构和数据创建一个表。

      2. 创建一个存储过程。

      3. 现在我知道我的过程的结果是什么,所以我正在执行以下查询。

         CREATE TABLE [dbo].[tblTestingTree](
             [Id] [int] IDENTITY(1,1) NOT NULL,
             [ParentId] [int] NULL,
             [IsLeft] [bit] NULL,
             [IsRight] [bit] NULL,
         CONSTRAINT [PK_tblTestingTree] PRIMARY KEY CLUSTERED
         (
             [Id] ASC
         ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
         ) ON [PRIMARY]
         GO
         SET IDENTITY_INSERT [dbo].[tblTestingTree] ON
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (1, NULL, NULL, NULL)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (2, 1, 1, NULL)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (3, 1, NULL, 1)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (4, 2, 1, NULL)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (5, 2, NULL, 1)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (6, 3, 1, NULL)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (7, 3, NULL, 1)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (8, 4, 1, NULL)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (9, 4, NULL, 1)
         INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (10, 5, 1, NULL)
        
         SET IDENTITY_INSERT [dbo].[tblTestingTree] OFF
         VALUES (10, 5, 1, NULL)
         SET IDENTITY_INSERT [dbo].[tblTestingTree] On
        
        
         create procedure GetDate
         as
         begin
             select Id,ParentId from tblTestingTree
         end
        
         create table tbltemp
         (
             id int,
             ParentId int
         )
         insert into tbltemp
         exec GetDate
        
         select * from tbltemp;
        

      【讨论】:

        【解决方案17】:

        如果查询不包含参数,则使用OpenQuery,否则使用OpenRowset

        基本的事情是根据存储过程创建模式并插入到该表中。例如:

        DECLARE @abc TABLE(
                          RequisitionTypeSourceTypeID INT
                        , RequisitionTypeID INT
                        , RequisitionSourcingTypeID INT
                        , AutoDistOverride INT
                        , AllowManagerToWithdrawDistributedReq INT
                        , ResumeRequired INT
                        , WarnSupplierOnDNRReqSubmission  INT
                        , MSPApprovalReqd INT
                        , EnableMSPSupplierCounterOffer INT
                        , RequireVendorToAcceptOffer INT
                        , UseCertification INT
                        , UseCompetency INT
                        , RequireRequisitionTemplate INT
                        , CreatedByID INT
                        , CreatedDate DATE
                        , ModifiedByID INT
                        , ModifiedDate DATE
                        , UseCandidateScheduledHours INT
                        , WeekEndingDayOfWeekID INT
                        , AllowAutoEnroll INT
                        )
        INSERT INTO @abc
        EXEC [dbo].[usp_MySp] 726,3
        SELECT * FROM @abc
        

        【讨论】:

          【解决方案18】:

          代码

          CREATE TABLE #T1
          (
              col1 INT NOT NULL,
              col2 NCHAR(50) NOT NULL,
              col3 TEXT NOT NULL,
              col4 DATETIME NULL,
              col5 NCHAR(50) NULL,
              col6 CHAR(2) NULL,
              col6 NCHAR(100) NULL,
              col7 INT NULL,
              col8 NCHAR(50) NULL,
              col9 DATETIME NULL,
              col10 DATETIME NULL
          )
          
          DECLARE @Para1 int
          DECLARE @Para2 varchar(32)
          DECLARE @Para3 varchar(100)
          DECLARE @Para4 varchar(15)
          DECLARE @Para5 varchar (12)
          DECLARE @Para6 varchar(1)
          DECLARE @Para7 varchar(1)
          
          
          SET @Para1 = 1025
          SET @Para2 = N'6as54fsd56f46sd4f65sd'
          SET @Para3 = N'XXXX\UserName'
          SET @Para4 = N'127.0.0.1'
          SET @Para5 = N'XXXXXXX'
          SET @Para6 = N'X'
          SET @Para7 = N'X'
          
          INSERT INTO #T1
          (
              col1,
              col2,
              col3,
              col4,
              col5,
              col6,
              col6,
              col7,
              col8,
              col9,
              col10,
          )
          EXEC [dbo].[usp_ProcedureName] @Para1, @Para2, @Para3, @Para4, @Para5, @Para6, @Para6
          

          我希望这会有所帮助。请酌情给予资格。

          【讨论】:

            【解决方案19】:

            我找到了 Passing Arrays/DataTables into Stored Procedures,这可能会让您对如何解决问题有另一个想法。

            该链接建议使用 Image 类型的参数来传递到存储过程。然后在存储过程中,将图像转化为包含原始数据的表变量。

            也许有一种方法可以与临时表一起使用。

            【讨论】:

            • 随着 Table Value Parameters 的引入,在 Sql2008 及更高版本中不再需要此功能。现在您可以直接将 .net 数据集或数据表对象传递给 sql 存储过程,而必须按照上面链接中的说明转换为字节
            【解决方案20】:

            我遇到了同样的问题,这是我从Paul's suggestion 所做的。这里的主要部分是使用NEWID()来避免多个用户同时运行存储过程/脚本,全局临时表的痛苦。

            DECLARE @sql varchar(max) = '', 
            @tmp_global_table varchar(255) = '##global_tmp_' + CONVERT(varchar(36), NEWID())
            SET @sql = @sql + 'select * into [' + @tmp_global_table + '] from YOURTABLE'
            EXEC(@sql)
            
            EXEC('SELECT * FROM [' + @tmp_global_table + ']')
            

            【讨论】:

              【解决方案21】:

              另一种方法是创建一个类型并使用 PIPELINED 传回您的对象。然而,这仅限于了解列。但它的优势是能够做到:

              SELECT * 
              FROM TABLE(CAST(f$my_functions('8028767') AS my_tab_type))
              

              【讨论】:

              • 这是什么?似乎与这个问题所涉及的 SQL Server 无关
              【解决方案22】:

              这可以在 SQL Server 2014+ 中完成,前提是存储过程只返回一个表。如果有人找到对多个表执行此操作的方法,我很想知道。

              DECLARE @storedProcname NVARCHAR(MAX) = ''
              SET @storedProcname = 'myStoredProc'
              
              DECLARE @strSQL AS VARCHAR(MAX) = 'CREATE TABLE myTableName '
              
              SELECT @strSQL = @strSQL+STUFF((
              SELECT ',' +name+' ' + system_type_name 
              FROM sys.dm_exec_describe_first_result_set_for_object (OBJECT_ID(@storedProcname),0)
              FOR XML PATH('')
              ),1,1,'(') + ')'
              
              EXEC (@strSQL)
              
              INSERT INTO myTableName
              
              EXEC ('myStoredProc @param1=1, @param2=2')
              
              SELECT * FROM myTableName
              
              DROP TABLE myTableName
              

              这会从系统表中提取返回表的定义,并使用它为您构建临时表。然后,您可以如前所述从存储过程中填充它。

              还有一些变体也适用于动态 SQL。

              【讨论】:

              • 对于早期版本的 SQL Server,存储过程 sp_describe_first_result_set 做的事情几乎相同。有一篇博客文章与您的回答大致相同:Using a temporary table to handle sp_describe_first_result_set 从另一个结果集中创建一个表。然后插入到创建的表中。如果 MS 实现了 SELECT INTO 的 EXEC 版本,我们就不会有这种悲伤。感谢您唤醒我的记忆!
              【解决方案23】:

              这是一个简单的两步过程: - 创建一个临时表 - 插入到临时表中。

              执行相同操作的代码:

              CREATE TABLE #tempTable (Column1 int, Column2 varchar(max));
              INSERT INTO #tempTable 
              EXEC [app].[Sproc_name]
              @param1 = 1,
              @param2 =2;
              

              【讨论】:

                【解决方案24】:

                在四处搜索之后,我找到了一种无需使用 OPENROWSETOPENQUERY 使用存储过程结果定义的通用架构为任何存储过程动态创建临时表的方法,尤其是当您不是数据库管理员时。

                Sql server 有一个内置的 proc sp_describe_first_result_set 可以为您提供任何过程结果集的架构。我根据此过程的结果创建了一个模式表,并手动将所有字段设置为 NULLABLE。

                declare @procname varchar(100) = 'PROCEDURENAME' -- your procedure name
                declare @param varchar(max) = '''2019-06-06''' -- your parameters 
                declare @execstr nvarchar(max) = N'exec ' + @procname
                declare @qry nvarchar(max)
                
                -- Schema table to store the result from sp_describe_first_result_set.
                create table #d
                (is_hidden  bit  NULL, column_ordinal   int  NULL, name sysname NULL, is_nullable   bit  NULL, system_type_id   int  NULL, system_type_name nvarchar(256) NULL,
                max_length  smallint  NULL, precision   tinyint  NULL,  scale   tinyint  NULL,  collation_name  sysname NULL, user_type_id  int NULL, user_type_database    sysname NULL,
                user_type_schema    sysname NULL,user_type_name sysname NULL,assembly_qualified_type_name   nvarchar(4000),xml_collection_id    int NULL,xml_collection_database    sysname NULL,
                xml_collection_schema   sysname NULL,xml_collection_name    sysname NULL,is_xml_document    bit  NULL,is_case_sensitive bit  NULL,is_fixed_length_clr_type  bit  NULL,
                source_server   sysname NULL,source_database    sysname NULL,source_schema  sysname NULL,source_table   sysname NULL,source_column  sysname NULL,is_identity_column bit NULL,
                is_part_of_unique_key   bit NULL,is_updateable  bit NULL,is_computed_column bit NULL,is_sparse_column_set   bit NULL,ordinal_in_order_by_list   smallint NULL,
                order_by_list_length    smallint NULL,order_by_is_descending    smallint NULL,tds_type_id   int  NULL,tds_length    int  NULL,tds_collation_id  int NULL,
                tds_collation_sort_id   tinyint NULL)
                
                
                -- Get result set definition of your procedure
                insert into #d
                EXEC sp_describe_first_result_set @exestr, NULL, 0
                
                -- Create a query to generate and populate a global temp table from above results
                select 
                @qry = 'Create table ##t(' +
                stuff(  
                    (select ',' + name + ' '+ system_type_name + ' NULL'
                    from #d d For XML Path, TYPE)
                    .value(N'.[1]', N'nvarchar(max)')
                , 1,1,'')
                + ')
                
                insert into ##t 
                Exec '+@procname+' ' + @param
                
                Exec sp_executesql @qry
                
                -- Use below global temp table to query the data as you may
                select * from ##t
                
                -- **WARNING** Don't forget to drop the global temp table ##t.
                --drop table ##t
                drop table #d 
                

                在 Sql Server 版本上开发和测试 - Microsoft SQL Server 2016 (RTM) - 13.0.1601.5(Build 17134:)

                您可以调整您正在使用的 SQL Server 版本的架构(如果需要)。

                【讨论】:

                  【解决方案25】:

                  如果您知道要传递的参数并且您无权使用 make sp_configure,则使用这些参数编辑存储过程,并且可以将它们存储在 ##global 表中。

                  【讨论】:

                    【解决方案26】:

                    这个问题迟到了几年,但我需要这样的东西来快速生成一些肮脏的代码。我相信正如其他人所说,预先定义临时表更容易,但这种方法应该适用于简单的存储过程查询或 sql 语句。

                    这会有点令人费解,但它借鉴了这里的贡献者以及来自 DBA Stack Exchange Get stored procedure result column-types 的 Paul White 的解决方案。再次重申,这种方法和示例不是为多用户环境中的流程设计的。在这种情况下,表定义会在全局临时表中设置一小段时间,以供代码生成模板进程参考。

                    我尚未对此进行全面测试,因此可能会有一些警告,因此您可能需要访问 Paul White 答案中的 MSDN 链接。这适用于 SQL 2012 及更高版本。

                    首先使用类似于Oracle 描述的存储过程sp_describe_first_result_set

                    这将评估第一个结果集的第一行,因此如果您的存储过程或语句返回多个查询,它将只描述第一个结果。

                    我创建了一个存储过程来分解返回单个字段以从中选择以创建临时表定义的任务。

                    CREATE OR ALTER PROCEDURE [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet]
                    (
                         @sql NVARCHAR(4000)
                        ,@table_name VARCHAR(100)
                        ,@TableDefinition NVARCHAR(MAX) OUTPUT
                    )
                    AS
                    BEGIN
                        SET NOCOUNT ON
                        DECLARE @TempTableDefinition NVARCHAR(MAX)
                        DECLARE @NewLine NVARCHAR(4) = CHAR(13)+CHAR(10)
                    
                        DECLARE @ResultDefinition TABLE (  --The View Definition per MSDN
                          is_hidden         bit NOT NULL
                        , column_ordinal    int NOT NULL
                        , [name]            sysname NULL
                        , is_nullable       bit NOT NULL
                        , system_type_id    int NOT NULL
                        , system_type_name  nvarchar(256) NULL
                        , max_length        smallint NOT NULL
                        , [precision]       tinyint NOT NULL
                        , scale             tinyint NOT NULL
                        , collation_name    sysname NULL    
                        , user_type_id      int NULL
                        , user_type_database    sysname NULL    
                        , user_type_schema  sysname NULL
                        , user_type_name    sysname NULL    
                        , assembly_qualified_type_name      nvarchar(4000)  
                        , xml_collection_id         int NULL
                        , xml_collection_database   sysname NULL    
                        , xml_collection_schema     sysname NULL    
                        , xml_collection_name       sysname NULL
                        , is_xml_document           bit NOT NULL            
                        , is_case_sensitive         bit NOT NULL            
                        , is_fixed_length_clr_type  bit NOT NULL    
                        , source_server             sysname NULL            
                        , source_database           sysname NULL
                        , source_schema             sysname NULL
                        , source_table              sysname NULL
                        , source_column             sysname NULL
                        , is_identity_column        bit NULL
                        , is_part_of_unique_key     bit NULL
                        , is_updateable             bit NULL
                        , is_computed_column        bit NULL
                        , is_sparse_column_set      bit NULL
                        , ordinal_in_order_by_list  smallint NULL   
                        , order_by_is_descending    smallint NULL   
                        , order_by_list_length      smallint NULL
                        , tds_type_id               int NOT NULL
                        , tds_length                int NOT NULL
                        , tds_collation_id          int NULL
                        , tds_collation_sort_id     tinyint NULL
                        )
                    
                        --Insert the description into table variable    
                        INSERT @ResultDefinition
                        EXEC sp_describe_first_result_set @sql
                    
                        --Now Build the string to create the table via union select statement
                        ;WITH STMT AS (
                            SELECT N'CREATE TABLE ' + @table_name + N' (' AS TextVal
                            UNION ALL
                    
                            SELECT 
                             CONCAT(
                                    CASE column_ordinal
                                        WHEN 1 THEN '     ' ELSE '   , ' END  --Determines if comma should precede
                                    , QUOTENAME([name]) , '   ', system_type_name  -- Column Name and SQL TYPE
                                    ,CASE is_nullable 
                                        WHEN 0 THEN '   NOT NULL' ELSE '   NULL' END --NULLABLE CONSTRAINT          
                                   ) AS TextVal
                            FROM @ResultDefinition WHERE is_hidden = 0  -- May not be needed
                            UNION ALL
                    
                            SELECT N');' + @NewLine
                        ) 
                    
                        --Now Combine the rows to a single String
                        SELECT @TempTableDefinition = COALESCE (@TempTableDefinition + @NewLine + TextVal, TextVal) FROM STMT
                    
                        SELECT @TableDefinition = @TempTableDefinition
                    END
                    

                    难题是您需要使用全局表,但您需要使其足够独特 因此,您可以频繁地从它中删除和创建,而不必担心碰撞。
                    在示例中,我使用 Guid (FE264BF5_9C32_438F_8462_8A5DC8DEE49E) 作为全局变量,用下划线替换连字符

                    DECLARE @sql NVARCHAR(4000) = N'SELECT @@SERVERNAME as ServerName, GETDATE() AS Today;'
                    DECLARE @GlobalTempTable VARCHAR(100) = N'##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable'
                    
                    --@sql can be a stored procedure name like dbo.foo without parameters
                    
                    DECLARE @TableDef NVARCHAR(MAX)
                    
                    DROP TABLE IF EXISTS #MyTempTable
                    DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
                    
                    EXEC [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet] 
                        @sql, @GlobalTempTable, @TableDef OUTPUT
                    
                    --Creates the global table ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
                    EXEC sp_executesql @TableDef 
                    
                    --Now Call the stored procedure, SQL Statement with Params etc.
                    INSERT ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
                        EXEC sp_executesql @sql 
                    
                    --Select the results into your undefined Temp Table from the Global Table
                    SELECT * 
                    INTO #MyTempTable
                    FROM ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
                    
                    SELECT * FROM #MyTempTable
                    
                    DROP TABLE IF EXISTS #MyTempTable
                    DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
                    

                    再一次,我只使用简单的存储过程查询和简单查询对其进行了测试,因此您的里程可能会有所不同。希望这对某人有所帮助。

                    【讨论】:

                      【解决方案27】:

                      这是我的带参数的 T-SQL

                      --require one time execution if not configured before
                      sp_configure 'Show Advanced Options', 1
                      GO
                      RECONFIGURE
                      GO
                      
                      --require one time execution if not configured before
                      sp_configure 'Ad Hoc Distributed Queries', 1
                      GO
                      RECONFIGURE
                      GO
                      
                      
                      --the query
                      DECLARE @param1 int = 1, @param2 int = 2
                      DECLARE @SQLStr varchar(max) = 'SELECT * INTO #MyTempTable
                                                      FROM OPENROWSET(''SQLNCLI'',  
                      ''Server=ServerName;Database=DbName;Trusted_Connection=yes'',
                      ''exec StoredProcedureName '+ CAST(@param1 AS varchar(15)) +','+ CAST(@param2 AS varchar(15)) +''') AS a ;
                       select * from #MyTempTable;
                       drop table #MyTempTable        
                      ';
                      EXECUTE(@SQLStr);
                      

                      【讨论】:

                        【解决方案28】:

                        好吧,您确实必须创建一个临时表,但它不必具有正确的架构....我创建了一个存储过程来修改现有的临时表,以便它具有所需的列正确的数据类型和顺序(删除所有现有列,添加新列):

                        GO
                        create procedure #TempTableForSP(@tableId int, @procedureId int)  
                        as   
                        begin  
                            declare @tableName varchar(max) =  (select name  
                                                                from tempdb.sys.tables 
                                                                where object_id = @tableId
                                                                );    
                            declare @tsql nvarchar(max);    
                            declare @tempId nvarchar(max) = newid();      
                            set @tsql = '    
                            declare @drop nvarchar(max) = (select  ''alter table tempdb.dbo.' + @tableName 
                                    +  ' drop column ''  + quotename(c.name) + '';''+ char(10)  
                                                           from tempdb.sys.columns c   
                                                           where c.object_id =  ' + 
                                                                 cast(@tableId as varchar(max)) + '  
                                                           for xml path('''')  
                                                          )    
                            alter table tempdb.dbo.' + @tableName + ' add ' + QUOTENAME(@tempId) + ' int;
                            exec sp_executeSQL @drop;    
                            declare @add nvarchar(max) = (    
                                                        select ''alter table ' + @tableName 
                                                              + ' add '' + name 
                                                              + '' '' + system_type_name 
                                                   + case when d.is_nullable=1 then '' null '' else '''' end 
                                                              + char(10)   
                                                      from sys.dm_exec_describe_first_result_set_for_object(' 
                                                       + cast(@procedureId as varchar(max)) + ', 0) d  
                                                        order by column_ordinal  
                                                        for xml path(''''))    
                        
                            execute sp_executeSQL  @add;    
                            alter table '  + @tableName + ' drop column ' + quotename(@tempId) + '  ';      
                            execute sp_executeSQL @tsql;  
                        end         
                        GO
                        
                        create table #exampleTable (pk int);
                        
                        declare @tableId int = object_Id('tempdb..#exampleTable')
                        declare @procedureId int = object_id('examplestoredProcedure')
                        
                        exec #TempTableForSP @tableId, @procedureId;
                        
                        insert into #exampleTable
                        exec examplestoredProcedure
                        

                        注意如果 sys.dm_exec_describe_first_result_set_for_object 无法确定存储过程的结果(例如,如果它使用临时表),这将不起作用。

                        【讨论】:

                          【解决方案29】:

                          如果您让动态 SQL 创建一个临时表,则该表属于动态 SQL 连接,而不是调用存储过程的连接。

                          DECLARE @COMMA_SEPARATED_KEYS varchar(MAX);
                          DROP TABLE IF EXISTS KV;
                          CREATE TABLE KV (id_person int, mykey varchar(30), myvalue int);
                          INSERT INTO KV VALUES
                          (1, 'age', 16),
                          (1, 'weight', 63),
                          (1, 'height', 175),
                          (2, 'age', 26),
                          (2, 'weight', 83),
                          (2, 'height', 185);
                          WITH cte(mykey) AS (
                              SELECT DISTINCT mykey FROM KV
                          ) 
                          SELECT @COMMA_SEPARATED_KEYS=STRING_AGG(mykey,',') FROM cte;
                          SELECT @COMMA_SEPARATED_KEYS AS keys;
                          

                          DECLARE @ExecuteExpression varchar(MAX);
                          
                          DROP TABLE IF EXISTS #Pivoted;
                          
                          SET @ExecuteExpression = N'
                          SELECT * 
                          INTO #Pivoted
                          FROM
                          (
                              SELECT
                                  mykey,
                                  myvalue,
                                  id_person
                              FROM KV
                          ) AS t
                          PIVOT(
                              MAX(t.myvalue) 
                              FOR mykey IN (COMMA_SEPARATED_KEYS)
                          ) AS pivot_table;
                          ';
                          
                          SET @ExecuteExpression = REPLACE(@ExecuteExpression, 'COMMA_SEPARATED_KEYS', @COMMA_SEPARATED_KEYS);
                          
                          EXEC(@ExecuteExpression);
                          
                          SELECT * FROM #Pivoted;
                          

                          消息 208,级别 16,状态 0 无效的对象名称“#Pivoted”。 这是因为 #Pivoted 归动态 SQL 连接所有。所以最后一条指令

                          SELECT * FROM #Pivoted
                          

                          失败。

                          避免遇到此问题的一种方法是确保对#Pivoted 的所有引用均来自动态查询本身:

                          DECLARE @COMMA_SEPARATED_KEYS varchar(MAX);
                          DROP TABLE IF EXISTS KV;
                          CREATE TABLE KV (id_person int, mykey varchar(30), myvalue int);
                          INSERT INTO KV VALUES
                          (1, 'age', 16),
                          (1, 'weight', 63),
                          (1, 'height', 175),
                          (2, 'age', 26),
                          (2, 'weight', 83),
                          (2, 'height', 185);
                          WITH cte(mykey) AS (
                              SELECT DISTINCT mykey FROM KV
                          ) 
                          SELECT @COMMA_SEPARATED_KEYS=STRING_AGG(mykey,',') FROM cte;
                          SELECT @COMMA_SEPARATED_KEYS AS keys;
                          
                          
                          DECLARE @ExecuteExpression varchar(MAX);
                          
                          DROP TABLE IF EXISTS #Pivoted;
                          
                          SET @ExecuteExpression = N'
                          SELECT * 
                          INTO #Pivoted
                          FROM
                          (
                              SELECT
                                  mykey,
                                  myvalue,
                                  id_person
                              FROM KV
                          ) AS t
                          PIVOT(
                              MAX(t.myvalue) 
                              FOR mykey IN (COMMA_SEPARATED_KEYS)
                          ) AS pivot_table;
                          SELECT * FROM #Pivoted;
                          ';
                          
                          SET @ExecuteExpression = REPLACE(@ExecuteExpression, 'COMMA_SEPARATED_KEYS', @COMMA_SEPARATED_KEYS);
                          
                          EXEC(@ExecuteExpression);
                          

                          【讨论】:

                          • 它是相同的“连接”和不同的“范围”(就像调用了定义本地临时表的嵌套 SP)。
                          【解决方案30】:

                          首先,修改您的存储过程以将最终结果保存到临时表中。通过这样做,我们正在创建一个与 SP 输出字段匹配的表。然后有一个选择语句将该临时表保存到任何表名。然后按照步骤 2 中的说明执行 SP

                          第 1 步:修改存储过程以将最终结果保存到临时表中

                          [your stored procedure] 
                          
                          into #table_temp //this will insert the data to a temp table
                          
                          from  #table_temp 
                          
                          select * into SP_Output_Table_1 from #table_temp //this will save data to a actual table
                          

                          第 2 步:执行下面的 SP,将记录插入到您的表中

                          Insert SP_Output_Table_1
                          EXE  You_SP_Nane @Parameter1 = 52, @parameter2 =1
                          

                          【讨论】:

                          猜你喜欢
                          • 2020-01-26
                          • 2018-07-05
                          • 1970-01-01
                          • 2021-01-10
                          • 2020-12-05
                          • 1970-01-01
                          • 2015-03-05
                          • 1970-01-01
                          相关资源
                          最近更新 更多