Get Table Structure of Stored Procedure Output Table

  • To get the results of a stored proc into a table you always had to know the structure of the output and create the table upfront.

    CREATE TABLE #Tmp (

    Key INT NOT NULL,

    Data Varchar );

    INSERT INTO #Tmp

    EXEC dbo.MyProc

    Has SQL 2012 (or SQL 2014) got any features / new tricks to let me discover the table structure of a stored procedure output, - i.e treat it as a table

    EXEC dbo.MyProc

    INTO #NewTmp

    or

    SELECT *

    INTO #NewTmp

    FROM ( EXEC dbo.MyProc )

  • Tom As far As I know, the trick to getting the column definitions is getting them into a temp table, so that piece is correct...

    the real trick is to call the procedure using a loopback linked server, so you can use openquery.

    EXEC master..sp_addlinkedserver

    @server = 'loopback',

    @srvproduct = '',

    @provider = 'SQLNCLI',

    @datasrc = @@SERVERNAME;

    EXEC master..sp_serveroption

    @server = 'loopback',

    @optname = 'DATA ACCESS',

    @optvalue = 'TRUE';

    SELECT * INTO #Tmp FROM OPENQUERY(loopback, 'EXEC CurrentDB.dbo.MyProc;');

    then you can select the data types form tempdb:

    SELECT

    colz.name,

    type_name(colz.system_type_id),

    colz.max_length, --doubled if this is an nvarchar/nchar ie 512 is nvarchar(256)

    colz.precision, --needed if decimal/numeric/money, mostly optional if float/real

    colz.scale

    from tempdb.sys.columns colz

    where object_id = object_id('tempdb.dbo.#Tmp')

    order by colz.column_id

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • Thanks

    I must be getting old because I've used OPENROWSET before in other projects, and didn't remember at all when posting this question.

    However on this particular project they don't like linked servers/openquery etc - So I don't have the Access level required - and almost certainly the DBA here would not allow it into production.

    SELECT * INTO #Tmp

    FROM OPENROWSET('SQLNCLI', 'server=INSTANCE;trusted_connection=yes', 'exec DB.dbo.MyProc')

    '

    Msg 15281, Level 16, State 1, Line 1

    SQL Server blocked access to STATEMENT 'OpenRowset/OpenDatasource' of component 'Ad Hoc Distributed Queries' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Ad Hoc Distributed Queries' by using sp_configure. For more information about enabling 'Ad Hoc Distributed Queries', search for 'Ad Hoc Distributed Queries' in SQL Server Books Online.

    But I was rather hoping Microsoft had built-in something new - without the need to shell out of T-SQL and reconnect.

    Maybe I'll write a CLR and try to squeeze that past the DBA :w00t:

  • I vaguely recalled something about SQL Server 2012 adding some additional system stored procedures that return a resultset describing metadata that would be returned from a specified batch of T-SQL, which could be a stored procedure.

    sp_describe_first_result_set

    http://technet.microsoft.com/en-us/library/ff878602.aspx

    For example:

    exec sp_describe_first_result_set @tsql = N'sp_who';

    However, it can be tripped up by dynamic sql. If you try it with sp_who2, it will return this:

    Msg 11526, Level 16, State 1, Procedure sp_describe_first_result_set, Line 1

    The metadata could not be determined because statement 'delete #tb1_sysprocesses

    where lower(status) = 'sleeping'

    and upper(cmd)' in procedure 'sp_who2' uses a temp table.

    Also in 2012 the EXEC command has a new WITH RESULT SETS clause that can be used to alias column names returned from a stored procedure.

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

  • There where two table value functions introduced in 2012, sys.dm_exec_describe_first_result_set and sys.dm_exec_describe_first_result_set_for_object, the former takes a query string as a parameter, the latter an object id. The result sets are the same.

    select * from sys.dm_exec_describe_first_result_set('exec sp_who',NULL,1);

    select * from sys.dm_exec_describe_first_result_set_for_object(object_id('sys.sp_who'),1);

  • Ok... I have to ask. What do either of those functions do for creating a table other than returning some meta-data that you could write some dynamic T-SQL to build a CREATE TABLE statement?

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Tom Brown (4/15/2014)


    However on this particular project they don't like linked servers/openquery etc - So I don't have the Access level required - and almost certainly the DBA here would not allow it into production.

    Shifting subjects a bit, you'd love me as a DBA. 🙂 I give the Devs "SA" privs on the Dev box (ONLY) and tell them to "Go for it, the sky's the limit. Just don't do any DBA stuff. If you need something like a linked server, come see me and we'll hammer it out together." I also tell them "You write it, I'll figure out a way to run it safely or a way to rewrite it so it is". I also do 100% code reviews that I use as "one-on-one mentoring" time and, I can assure you, the Devs aren't the only ones learning during such sessions. 😉

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff Moden (4/20/2014)


    Ok... I have to ask. What do either of those functions do for creating a table other than returning some meta-data that you could write some dynamic T-SQL to build a CREATE TABLE statement?

    From the top of my head:w00t:

    As a coding and s documentation aide, fastest method for optaining the metadata and structure (my favorite).

    For tracking / monitoring / auditing changes and asserting design compliance. Dump the results in a table...

    Optaining the metadata translation for SSIS packages, which i.e. create staging tables based on the metadata. Far better than writing a translation routine in the package.

    Adding a level of security to dynamic sql routines, similar to the INFORMATION_SCHEMA. An object or a column cannot be used in any way, shape or form unless it exists in the function's result set.

    BTW: The functions use an undocumented source definition (TABLE) within OPENROWSET, haven't looked further into that part:cool:

  • Heh... Thanks. I guess I'd just have to curse any DBA that doesn't allow the use of OPENROWSET for such things. The end user of the proc don't need anything other than PUBLIC privs if it's done right.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff Moden (4/20/2014)


    Tom Brown (4/15/2014)


    However on this particular project they don't like linked servers/openquery etc - So I don't have the Access level required - and almost certainly the DBA here would not allow it into production.

    Shifting subjects a bit, you'd love me as a DBA. 🙂 I give the Devs "SA" privs on the Dev box (ONLY) and tell them to "Go for it, the sky's the limit. Just don't do any DBA stuff. If you need something like a linked server, come see me and we'll hammer it out together." I also tell them "You write it, I'll figure out a way to run it safely or a way to rewrite it so it is". I also do 100% code reviews that I use as "one-on-one mentoring" time and, I can assure you, the Devs aren't the only ones learning during such sessions. 😉

    What is a DBA to do when the Dev or BI team insists that they need access to the "SA" account, and managment agrees with them?

    Below is one solution. 😉

    use MASTER

    go

    alter login sa DISABLE;

    go

    alter login sa with name = [sa_bak];

    go

    create login sa with PASSWORD = '<strong password>', DEFAULT_DATABASE = master;

    go

    use CorpDb;

    go

    drop user sa;

    go

    create USER sa for login sa;

    go

    exec sp_addrolemember 'db_datareader', 'sa';

    -- etc. whatever other minimal persmissions they need.

    go

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

  • Eric M Russell (4/21/2014)


    Jeff Moden (4/20/2014)


    Tom Brown (4/15/2014)


    However on this particular project they don't like linked servers/openquery etc - So I don't have the Access level required - and almost certainly the DBA here would not allow it into production.

    Shifting subjects a bit, you'd love me as a DBA. 🙂 I give the Devs "SA" privs on the Dev box (ONLY) and tell them to "Go for it, the sky's the limit. Just don't do any DBA stuff. If you need something like a linked server, come see me and we'll hammer it out together." I also tell them "You write it, I'll figure out a way to run it safely or a way to rewrite it so it is". I also do 100% code reviews that I use as "one-on-one mentoring" time and, I can assure you, the Devs aren't the only ones learning during such sessions. 😉

    What is a DBA to do when the Dev or BI team insists that they need access to the "SA" account, and managment agrees with them?

    Below is one solution. 😉

    use MASTER

    go

    alter login sa DISABLE;

    go

    alter login sa with name = [sa_bak];

    go

    create login sa with PASSWORD = '<strong password>', DEFAULT_DATABASE = master;

    go

    use CorpDb;

    go

    drop user sa;

    go

    create USER sa for login sa;

    go

    exec sp_addrolemember 'db_datareader', 'sa';

    -- etc. whatever other minimal persmissions they need.

    go

    Oh you sneaky devil you! 😛 Nice!

    Fortunately for me and for any of the jobs I've had, all I have to do is remind management that they won't pass a SOC 2, SOX, SEC, PCI, or any other type of audit if they grant users/apps "SA" privs on the servers that I'm responsible for (and that would be all of them) and they suddenly backoff and listen to what actually needs to be done. 😛

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff Moden (4/21/2014)


    Eric M Russell (4/21/2014)


    Jeff Moden (4/20/2014)


    Tom Brown (4/15/2014)


    However on this particular project they don't like linked servers/openquery etc - So I don't have the Access level required - and almost certainly the DBA here would not allow it into production.

    Shifting subjects a bit, you'd love me as a DBA. 🙂 I give the Devs "SA" privs on the Dev box (ONLY) and tell them to "Go for it, the sky's the limit. Just don't do any DBA stuff. If you need something like a linked server, come see me and we'll hammer it out together." I also tell them "You write it, I'll figure out a way to run it safely or a way to rewrite it so it is". I also do 100% code reviews that I use as "one-on-one mentoring" time and, I can assure you, the Devs aren't the only ones learning during such sessions. 😉

    What is a DBA to do when the Dev or BI team insists that they need access to the "SA" account, and managment agrees with them?

    Below is one solution. 😉

    use MASTER

    go

    alter login sa DISABLE;

    go

    alter login sa with name = [sa_bak];

    go

    create login sa with PASSWORD = '<strong password>', DEFAULT_DATABASE = master;

    go

    use CorpDb;

    go

    drop user sa;

    go

    create USER sa for login sa;

    go

    exec sp_addrolemember 'db_datareader', 'sa';

    -- etc. whatever other minimal persmissions they need.

    go

    Oh you sneaky devil you! 😛 Nice!

    Fortunately for me and for any of the jobs I've had, all I have to do is remind management that they won't pass a SOC 2, SOX, SEC, PCI, or any other type of audit if they grant users/apps "SA" privs on the servers that I'm responsible for (and that would be all of them) and they suddenly backoff and listen to what actually needs to be done. 😛

    Yes, fortunately I havn't had to do this in my current job thanks to SOX and HIPAA, and also I'm on the Dev/Ops side of things now. However, I have reccomended it to a lot DBAs here and at user group meetings. Often times the question isn't "Should I grant developers access to 'SA' account?" but rather "How do I deal with developers who have access to 'SA' account?". It's especially useful in small organizations where the DBA might not have any political clout.

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

  • Well our current DBA has been referred to (and I quote) as "slash dev slash null" - (which seems to have multiple meanings ) - but the one in point is he doesn't listen to or even acknowledge any requests for anything outside your current permission set. [developer request] > /dev/null

    I think the company got burned over a security breach a few years back, and now everything is locked down tight as a kangaroo's Khyber.

    Meanwhile, back to the original question, this seems to serve my purposes for now - thanks to those who knew about the new dm

    DECLARE @SPNAME sysname;

    SET @SPNAME = 'usp_GetUsers';

    DECLARE @TMPTABLE sysname;

    SET @TMPTABLE = N'#' + @SPNAME;

    DECLARE @DELIM NVARCHAR(4) = N', ' + NCHAR(10);

    DECLARE @SQL NVARCHAR(MAX);

    SET @SQL = N'CREATE TABLE ' + @TMPTABLE + N' ( ';

    WITH rowDefs AS (

    select TOP(100) PERCENT name + ' ' + system_type_name AS RowDef, column_ordinal

    FROM sys.dm_exec_describe_first_result_set(N'exec ' + @SPNAME,NULL,1)

    WHERE is_hidden = 0

    ORDER BY column_ordinal

    )

    SELECT DISTINCT

    @SQL = @SQL + stuff ( ( SELECT @DELIM + RowDef

    FROM rowDefs t1

    FOR XML PATH ( '' ) ) , 1 , 1 , '' )

    FROM rowDefs t2

    SELECT @SQL = @SQL + N' );'

    PRINT @SQL;

    However, today being a bank holiday, I haven't had change to test this at work yet - surely they wouldn't have locked out permissions to the sys.dm tools - actually they may have, if any of those sys.dm procedures allow you to do anything remotely suspicious from a security point of view, I can see a blanket ban being imposed on all of them.

  • Given the cirsunstances, it's probably best to just hard code the definition of the temp table, which is the typical way of doing it. I wouldn't even dick around with doing this dynamically in the first place.

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

  • Hi,

    I started crashing my head on this topic, so I ask some further advice to the people that, seemingly, tried to solve the same problem.

    In this situation I'm a report designer that writes the query used in the report relying on a stored procedure (that uses temporary tables inside it) written by someone else.

    I must take the result of the stored procedure, put it into (another) temporary table, JOIN it with other tables ...

    I this "someone else" adds some columns to the output, the report query breaks :angry:.

    Until now I was unable to find any solution to this problem.

    Did anybody of you ?

    Thanks

    Teodoro Marinucci

Viewing 15 posts - 1 through 15 (of 16 total)

You must be logged in to reply to this topic. Login to reply