Getting xml as result from exec stored procedure - sql-server

I'm trying to get the result of an executed stored procedure to be retrieved as a XML of the table the result is shown as originally.
What I'm trying to do is somthing like this.
exec dbo.StoredProcedure FOR XML RAW, ROOT ('root_name').
Lets say exec dbo.StoredProcedure returns the table in the Stored Procedure,
I want the FOR XML RAW, ROOT ('root_name') to return the XML value of that whole result.
How do I achieve this In SQL server?

One method is to insert the proc results into a temp table or variable using INSERT...EXEC and then select from that table with the desired FOR XML query:
DECLARE #results AS TABLE(col1 int, col2 int);
INSERT INTO #results EXEC dbo.StoredProcedure;
SELECT col1, col2
FROM #results
FOR XML RAW, ROOT ('root_name');

As per this question, you should not select from the stored procedure. Also if you dig into that question, you will find a link to an interesting article describing options you have with stored procedures.
If I were you I would either return an XML with an output parameter, or insert-exec into a table and then query it with for xml.

Related

How can I transform the result of a stored procedure into xml on the sql server?

I have a stored procedure that can NOT be modified, the result of this stored procedure is normal select statement as following :
CREATE PROCEDURE LockedProcedure
AS
BEGIN
SELECT * FROM COLORS_TABLE
END
my problem is that I need to get its result as XML result like how the select statement returns when you provide "FOR XML" but without modifying the procedure itself, maybe we can create another stored procedure to call that or user defined function.
This is an example of the procedure that we CAN NOT modify because it is locked.
how to get its result as XML result NOT XML FILE...I don't want any physical file on hard disk.
Thanks.
Solution 1)
Create a temp table matching the output definition of stored procedure.
Use INSERT INTO #Tmp EXEC SPName to insert the stored procedure results into the temp table.
Use FOR XML in combination with SELECT command to fetch the results as xml from temp table.
Solution 2)
Create a CLR User-Defined function to execute the stored procedure and use the BCL facilities to convert the results to xml.
I had a similar problem to this but in my case editing the stored procedure is possible. Even though the OP mentions the stored procedure is locked, I still wanted to post this solution here for others that stumble upon it. This solution assumes the stored procedure uses dynamic SQL to select some data, but could just as easily be adapted to a non-dynamic SQL case.
Add a parameter to the sp such as "#lp_ReturnAsXML BIT = 0". When set to true, you will return the result set as XML using "FOR XML RAW" or some similar command.
Then add this to the end of the stored procedure as an alternative for running the dynamic SQL:
IF #lp_ReturnAsXML = 1
BEGIN
DECLARE #l_XML XML
SET #l_SQL = 'SET #l_XML = (SELECT * FROM ( ' +
#l_SQL + '
) d FOR XML RAW)'
EXEC sp_executesql #l_SQL, N'#l_XML XML OUTPUT', #l_XML = #l_XML OUTPUT
SELECT #l_XML
END
Now something like this should work:
DECLARE #table TABLE
(
Results XML
)
INSERT INTO #table
EXEC p_MyStoredProc ..., #lp_ReturnAsXML = 1

how can i run a where Clause to stored Procedure without edit it in SQL Server?

if i have a SQL SERVER 2008 Stored Procedure that return a table of result , is it possible to run a WHERE Clause to the result table with out editing the stored procedure itself ?
Not directly.
Redirect the output to a temp table. Select and filter from that
CREATE TABLE #foo (...)
INSERT #foo EXEC bar #p1
SELECT * FROM #foo WHERE ...
I would suggest creating a #temp table to insert the results from the stored procedure into and then selecting from that with the WHERE clause.
You could make use of a Table Valued Function, and combine this with the other answers here ... ie: Create a TVF which creates a connection-local temporary table, populates that table with the results of the Stored Procedure call and returns the results. You can then do a SELECT from that TVF applying the desired WHERE clause.
Though, this could be very slow with large datasets!!
Openrowset is an option which comes into my mind it works like this
SELECT *
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off exec master.dbo.sp_who')
AS tbl
You can apply where clause directly.

How to convert a SQL Server result set to XML after the fact?

Is there a way to cause the result set of a SQL Server stored procedure (or any result set, after the fact) to be encoded in XML format?
I want the result set to be encoded in XML as if the FOR XML RAW clause was used during selection.
However the complex stored procedure logic and its internal SELECT statements should not be modified to return XML because the procedure is used for its standard/non-XML result set most of the time.
Update: Emphasis on the fact I'm looking for an answer in the SQL Server environment - the
results should be returned as if SQL Server has directly encoded them itself, as XML, just like it does when using the built-in XML features like the FOR XML clause.
You would insert the data from the SP into a temp table, then select from that FOR XML
This won't work if the SP itself already does a INSERT .. EXEC SPROC because you cannot nest them
Working examples
use tempdb;
create proc giveme
as
select a = 1, b = GETDATE()
union all
select 2, b = '20100101'
Using INSERT.. EXEC
declare #t table (a int, b datetime)
insert #t
exec giveme
select * from #t for xml raw
Using OPENQUERY
exec sp_addlinkedserver 'localhost'
exec sp_serveroption #server = 'localhost'
,#optname = 'DATA ACCESS'
,#optvalue = 'TRUE'
select *
from openquery(localhost, 'exec tempdb..giveme')
for xml raw
You could try using OPENROWSET in cooperation with FOR XML to do the transformation.
By 'after the fact', do you mean still within the SQL Server environment? Or are you talking about a client program?
Within SQL, you could probably write a sproc that acts as a wrapper for your other sprocs, along these lines. The wrapper sproc would handle the FOR XML work.
In .NET, there are a number of ways to do this.
You can try inserting the result set from the stored procedure into a table variable( or temporary table) and selecting the table rows with the FOR XML clause.
Here is an example:
DECLARE #MyDataTable AS TABLE ( col1 int,...., colN int)
Make sure that the #MyDataTable has the same columns as the stored procedure result set(s).
INSERT INTO #MyDataTable
EXECUTE mysp_GetData #param1=value,....,#paramN;
SELECT * FROM #MyDataTable
FOR XML AUTO

functional reason why stored procedures don't support INSERT/EXECUTE INTO?

In SQL Server, there's no way to create a temp table on the fly from the results of a stored procedure, ala:
CREATE TABLE #temptable AS
EXEC spMyStoredProc
or
EXEC spMyStoredProc INTO #temptable
or something like that. Instead, you have to know the SP layout beforehand, and have to do something like this:
CREATE TABLE #temptable (col1 INT, col2 VARCHAR(255))
INSERT INTO #temptable
EXEC spMyStoredProc
Is there a functional reason why this is the case? Maybe a limitation of SQL Server? Or is it just something that hasn't been added to the SQL spec yet, and I can hold out hope that one day they'll support it?
A stored procedure can return many result sets, or none, and it can vary entirely depending upon the execution of the stored procedure.
When it is compiled it's meta-information does not describe it as having any specific expectable result set output.
I expect given those constraints, they elected not to implement this because of the lack of strong typing of what a stored procedure may return.
Not from a sproc, but you can use tabled values functions to do something similar.
Select * From fnMyFunction
You'd be able to insert into a # table if you desired.
Try this out
DECLARE #temptable TABLE (ID INT, NAME VARCHAR(255))
declare #query varchar(max)
set #query='Select whatever from whereever'
INSERT INTO #temptable
EXEC (#Query)
select *from #temptable
If I needed such functionality I would use an inline UDF, like this:
CREATE PROCEDURE MySample
AS
SELECT a,b,c FROM dbo.MyInlineUDF(1,2,3)
GO
SELECT * INTO #t
FROM dbo.MyInlineUDF(1,2,3) WHERE 1=0
INSERT INTO #t EXEC MySample

Creating a stored procedure to return the rowcount of another stored procedure

Is it possible to do this? I have some filters set in my source Stored Procedure and I really don't want to have to duplicate it in another just to get the rowcount.
The only way I know how to do this is to insert into a temp table from the stored procedure and then select the count. Unfortunately, there's no pretty way to perform a "select" on a stored procedure.
CREATE TABLE #stuff (id int, status char(6))
INSERT #stuff (id, status)
EXEC dbo.sp_get_stuff
SELECT count(*) FROM #stuff
DROP TABLE #stuff
Edit
The above method will allow you to select from a stored procedure, but as Greg pointed out, a rowcount can be simplified to:
EXEC dbo.sp_get_stuff
SELECT ##Rowcount
This also works:
create proc pTest1
as
select * from comp
go
create proc pTest2
as
exec pTest1
select ##rowcount
GO
If you are really trying to fine tune as much as possible, then you will have to change the source stored procedure. If you are looking at performance, then returning the rowset just to get the count is not something to even consider.

Resources