2

I am using SQL Server 2008 R2 and am trying to get the results of a stored procedure into a temporary table that I can access later on in the calling stored proc. My TSQL is as follows:

CREATE PROCEDURE sp_ToBeCalled AS
(
   @SomeParam INT
)
BEGIN
    SELECT * FROM tblSomeTable WHERE SomeField = @SomeParam 
END


CREATE PROCEDURE sp_CallingProcedure AS
(
   @SomeOtherParam INT
)
BEGIN
    -- A
    SELECT * INTO #MyTempTable FROM sp_ToBeCalled(@SomeOtherParam)

    -- B
    SELECT * FROM #MyTempTable FOR XML RAW
END

This all compiles fine however when I call sp_CallingProcedure statement -- B returns an error that #MyTempTable.

How can I do "A" so that I can access its results from within a #MyTempTable table without having to declare the structure of #MyTempTable first?

I am looking for a solution that I can use generically. I have a number of existing stored procedures that I need to call from various callers where getting the results queryable is a necessity. I cannot change the existing stored procedures.

I don't want to use

  1. OPENQUOERY() - requires a custom linked server definition
  2. sp_ExecSql() - means I have to build up dynamic SQL which does not give me SP compile time checking.
Kate Gregory
  • 18,808
  • 8
  • 56
  • 85
TheEdge
  • 9,291
  • 15
  • 67
  • 135
  • You might want to consider table valued functions as well – Sparky Apr 29 '13 at 22:29
  • You can use OPENROWSET instead of OPENQUERY to avoid a Linked Server definition. I've tried to get MS to implement an EXECUTE INTO but they closed as Won't Fix. https://connect.microsoft.com/SQLServer/feedback/details/675710/execute-into-to-capture-execute-results-in-a-new-table – GilM Apr 29 '13 at 22:37

2 Answers2

1

You are trying to use a Procedure like a tabular function.

Try using

INSERT INTO #MyTempTable (column1, column2...)
exec sp_ToBeCalled(@SomeOtherParam)
Amit Rai Sharma
  • 4,015
  • 1
  • 28
  • 35
  • 2
    OP didn't want to define the structure of the temp table before populating it. – GilM Apr 29 '13 at 22:45
  • So leave out the column list? – Nick.Mc Apr 30 '13 at 01:24
  • @Gilm: "TheEdge" is expecting to come up with a solution where he does not have to change store procedure and also not use dynamic sql and then create temp table on fly. We I am not sure how he is going to achieve it. He has to be bit flexible in his approach. He has been trying to use a stored procedure as a table function which is at present not supported by tsql. – Amit Rai Sharma Apr 30 '13 at 09:23
  • @ElectricLlama: Sorry I could not understand your comment. Which column you are referring here? – Amit Rai Sharma Apr 30 '13 at 09:24
  • 1
    Sorry my mistake, I thought you could use `INSERT INTO` without a column list but you can't. – Nick.Mc Apr 30 '13 at 09:33
0

A great reference: http://www.sommarskog.se/share_data.html

I managed to partially solve my issue by doing the following:

1) Custom Stored Procedure to select a ROWSET into a global temp table 2) Calling SP calls 1) and then transfers the ##GlobalTempTable into a local #TempTable for processing

This works but has the following "issues":

  • Potential security risk as "Adhoc Distributed Queries" functionality needs to be turned on
  • Still requires a Global Temp table that needs to be cleaned up by the caller. Temp table naming is also problematic as multiple 2) will cause an issue.

I include my code below in case it helps someone else. If anyone is able to improve on it please feel free to post.

/* This requires Adhoc Distributed Queries to be turned on:
   sp_configure 'Show Advanced Options', 1
   GO
   RECONFIGURE
   GO
   sp_configure 'Ad Hoc Distributed Queries', 1
   GO
   RECONFIGURE
   GO
*/

-- Adapted from: http://stackoverflow.com/questions/653714/how-to-select-into-temp-table-from-stored-procedure

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;Database=' + DB_NAME() + ''''

    SET @rowsetSql = '''EXEC ' + REPLACE(@storedProcWithParameters, '''', '''''') + ''''



    SET @sql = '
SELECT
    *
INTO 
    ' + @tableName + ' 
FROM
    OPENROWSET(' + @driver + ',' + @connectionString + ',' + @rowsetSql + ')'

    EXEC (@sql)
END
GO

and then to use in another SP as follows:

EXEC ExecIntoTable '##MyGlobalTable', 'sp_MyStoredProc 13, 1'
SELECT * 
INTO #MyLocalTable
FROM ##MyGlobalTable
DROP TABLE ##MyGlobalTable

SELECT * FROM #MyLocalTable
TheEdge
  • 9,291
  • 15
  • 67
  • 135