From: Behzad Sadeghi on
Is it possible to write a script that, as its input, takes the name of
a stored procedure, and, as its output, produces a table each of whose
rows contains the name and data type of each column in the (presumably
unique) result set of that stored procedure?

I am trying to build a system that can create a set of scripts that
can act as a test harness for a given stored procedure. I would like
to automate as much of this task as possible. Currently, I am
generating scripts that can read sets of parameters stored in a table,
invoke the stored procedure for each parameter set (represented by
each row), and collectively store the result sets returned by each
invocation of the procedure into another table, for comparison with
previous or future runs of the same tests.

To generate the tables which store the results, I need to know the
structure of the procedure's result sets. But, as of now, I cannot
think of a way to do this, except for visually inspecting the code of
the stored procedure and manually constructing a definition for the
result set. Can anyone help?

Behzad

From: Erland Sommarskog on
Behzad Sadeghi (behzad.sadeghi(a)gmail.com) writes:
> Is it possible to write a script that, as its input, takes the name of
> a stored procedure, and, as its output, produces a table each of whose
> rows contains the name and data type of each column in the (presumably
> unique) result set of that stored procedure?

For the general case, the answer is: no. A stored procedure can
theoretically generate a diffrently structured result set every time.

Nevertheless, there are many situations where client API needs to be
able to do this. As just one example, consider a query that uses
OPENQUERY(SERVER, 'EXEC that_sp'). For the local server to be able
to compile the query, it needs to determine the result set of the
remote query.

The mechanism used today is to issue the command SET FMTONLY ON. This
sets a kind of half-exec mode where SQL Server runs through all statements,
but do not actually run queries, but returns empty result sets with the
metadata. This method works so-so. There are a lot of situations where it
fails. The prime example is a procedure that creates a temp table,
and the performs action against this temp table. Since the table does not
get created in FMTONLY mode, queries that refers to the temp table fails.
Another potential problem is that in FMTONLY conditions for IF and WHILE
are no honored, but all branches are executed. A recursive stored procedure
will fail in FMTONLY mode, because of infinite recursion.

--
Erland Sommarskog, SQL Server MVP, esquel(a)sommarskog.se

Links for SQL Server Books Online:
SQL 2008: http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
SQL 2005: http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
SQL 2000: http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

From: Behzad Sadeghi on
Thank you, Erland.

Reading your answer, I realized I have another problem. Let's say I
run the stored procedure from within a T-SQL script, either using
FMTONLY or not. I will get a result set, either empty or not. Now, how
can I examine this result set to decipher its columnar structure from
within my T-SQL script? I know I can use "insert <myTable> exec
<myProc>", which will persist a table in my database, which I can then
examine using system catalog views. But for that, I already need to
know the structure of the result set. Is there a way to do this
(persist the result set to the database) without knowing its
structure. Again, I need to do all this from within T-SQL.

Behzad
From: Behzad Sadeghi on
On Jul 25, 11:44 pm, Jeroen Mostert <jmost...(a)xs4all.nl> wrote:
> On 2010-07-25 19:57, Behzad Sadeghi wrote:> Reading your answer, I realized I have another problem. Let's say I
> > run the stored procedure from within a T-SQL script, either using
> > FMTONLY or not. I will get a result set, either empty or not. Now, how
> > can I examine this result set to decipher its columnar structure from
> > within my T-SQL script? I know I can use "insert<myTable>  exec
> > <myProc>", which will persist a table in my database, which I can then
> > examine using system catalog views. But for that, I already need to
> > know the structure of the result set. Is there a way to do this
> > (persist the result set to the database) without knowing its
> > structure. Again, I need to do all this from within T-SQL.
>
> It's possible, but I wouldn't bother. SELECT * INTO ... FROM OPENQUERY(....,
> 'SET FMTONLY ON; EXEC ...') should give you a table to analyze. You'll need
> to add the local server as a linked server enabled for data access.
> OPENROWSET should also work, but this requires the "ad hoc distributed
> queries" server option to be changed.
>
> It is much more sane to do schema determination from client code (for
> example, using CommandBehavior.SchemaOnly in .NET, but other libraries will
> probably have similar options). Dynamic SQL is tricky enough without adding
> yet another layer of indirection, and T-SQL is a poor candidate for a
> general programming language. Robustness and maintainability are especially
> hard to achieve, which is rather undesirable for a testing harness.
>
> I doubt you really "need to do all this from within T-SQL": with a little
> more ingenuity and/or script-fu this shouldn't be necessary. Look into stuff
> like PowerShell and IronPython if you don't want to write complete
> applications. A complete, small C(++) application to do the tricky schema
> determination bits would also make sense.
>
> Something has to trigger executing that T-SQL. Unless it's a scheduled job,
> it should also give you an opportunity for executing client code.
>
> --
> J.

Thanks Jeroen. Lots to think about in your reply. Thanks again.
From: Erland Sommarskog on
Behzad Sadeghi (behzad.sadeghi(a)gmail.com) writes:
> Reading your answer, I realized I have another problem. Let's say I
> run the stored procedure from within a T-SQL script, either using
> FMTONLY or not. I will get a result set, either empty or not. Now, how
> can I examine this result set to decipher its columnar structure from
> within my T-SQL script? I know I can use "insert <myTable> exec
><myProc>", which will persist a table in my database, which I can then
> examine using system catalog views. But for that, I already need to
> know the structure of the result set. Is there a way to do this
> (persist the result set to the database) without knowing its
> structure. Again, I need to do all this from within T-SQL.

I can only agree with Jeroen, don't try do this from T-SQL, unless
you really love to hurt yourself. You can do it all in SQL Server if
you insist, but then you should write your discovery routines in C# ort
VB .Net. But it's probably better to have it it all in a client-side
program.


--
Erland Sommarskog, SQL Server MVP, esquel(a)sommarskog.se

Links for SQL Server Books Online:
SQL 2008: http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
SQL 2005: http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
SQL 2000: http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx