Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve column names and types of a stored procedure? [duplicate]

Tags:

sql

sql-server

Possible Duplicate:
Retrieve column definition for stored procedure result set

I use the following SQL to get column names and types for a table or view:

DECLARE @viewname varchar (250);  select a.name as colname,b.name as typename  from syscolumns a, systypes b -- GAH! where a.id = object_id(@viewname)  and a.xtype=b.xtype  and b.name <> 'sysname' 

How do I do something similar for the output columns of a stored procedure?

like image 925
Wang Wei Avatar asked Jan 29 '13 02:01

Wang Wei


People also ask

How can get column name in stored procedure in SQL Server?

sp_help procedure The sp_help procedure is used to get information about a current database object. The database object may be a table, view or stored procedure. To get a column name of a table we use sp_help with the name of the object or table name. sp_help will return all the column names of the object.

How copy all column names in SQL?

Select cells from the columns you want to copy (CTRL+Click), choose "Copy selected Headers" in Results grid context menu and column names will be copied to clipboard. This action creates a comma-separated list that can be pasted wherever you need.

How do I clone a stored procedure?

Launch MS SQL Server Management Studio in your system and go to the Object Explorer. Step 2. Right-click on the database from which you want to move data and then click on Tasks>>Generate Scripts… A Generate and Publish Scripts Wizard will appear on the screen, click on the Next button to proceed.


2 Answers

[I just realized I've answered this question before]

Doing this for a stored procedure is a lot more complicated than it is for a view or table. One of the problems is that a stored procedure can have multiple different code paths depending on input parameters and even things you can't control like server state, time of day, etc. So for example what you would expect to see as the output for this stored procedure? What if there are multiple resultsets regardless of conditionals?

CREATE PROCEDURE dbo.foo   @bar INT AS BEGIN   SET NOCOUNT ON;    IF @bar = 1     SELECT a, b, c FROM dbo.blat;   ELSE     SELECT d, e, f, g, h FROM dbo.splunge; END GO 

If your stored procedure does not have code paths and you are confident that you will always see the same result set (and can determine in advance what values should be supplied if a stored procedure has non-optional parameters), let's take a simple example:

CREATE PROCEDURE dbo.bar AS BEGIN   SET NOCOUNT ON;    SELECT a = 'a', b = 1, c = GETDATE(); END GO 

FMTONLY

One way is to do something like this:

SET FMTONLY ON; GO EXEC dbo.bar; 

This will give you an empty resultset and your client application can take a look at the properties of that resultset to determine column names and data types.

Now, there are a lot of problems with SET FMTONLY ON; that I won't go into here, but at the very least it should be noted that this command is deprecated - for good reason. Also be careful to SET FMTONLY OFF; when you're done, or you'll wonder why you create a stored procedure successfully but then can't execute it. And no, I'm not warning you about that because it just happened to me. Honest. :-)

OPENQUERY

By creating a loopback linked server, you can then use tools like OPENQUERY to execute a stored procedure but return a composable resultset (well, please accept that as an extremely loose definition) that you can inspect. First create a loopback server (this assumes a local instance named FOO):

USE master; GO EXEC sp_addlinkedserver @server = N'.\FOO', @srvproduct=N'SQL Server' GO EXEC sp_serveroption @server=N'.\FOO', @optname=N'data access',    @optvalue=N'true'; 

Now we can take the procedure above and feed it into a query like this:

SELECT * INTO #t  FROM OPENQUERY([.\FOO], 'EXEC dbname.dbo.bar;') WHERE 1 = 0;  SELECT c.name, t.name FROM tempdb.sys.columns AS c INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id WHERE c.[object_id] = OBJECT_ID('tempdb..#t'); 

This ignores alias types (formerly known as user-defined data types) and also may show two rows for columns defined as, for example, sysname. But from the above it produces:

name   name ----   -------- b      int c      datetime a      varchar 

Obviously there is more work to do here - varchar doesn't show length, and you'll have to get precision / scale for other types such as datetime2, time and decimal. But that's a start.

SQL Server 2012

There are some new functions in SQL Server 2012 that make metadata discovery much easier. For the above procedure we can do the following:

SELECT name, system_type_name FROM sys.dm_exec_describe_first_result_set_for_object (   OBJECT_ID('dbo.bar'),    NULL ); 

Among other things this actually provides precision and scale and resolves alias types for us. For the above procedure this yields:

name   system_type_name ----   ---------------- a      varchar(1) b      int c      datetime 

Not much difference visually but when you start getting into all the different data types with various precision and scale you'll appreciate the extra work this function does for you.

The downside: In SQL Server 2012 at least these functions only work for the first resultset (as the name of the function implies).

like image 100
Aaron Bertrand Avatar answered Sep 30 '22 06:09

Aaron Bertrand


Are you trying to return all the stored procedures and all of their parameters? Something like this should work for that.

select * from information_schema.parameters 

If you need to get the columns returned from a stored procedure, take a look here:

Get column names/types returned from a stored procedure

like image 31
sgeddes Avatar answered Sep 30 '22 06:09

sgeddes