Blog Post

T-SQL Enhancement: EXECUTE WITH RESULT SETS

,

All developers know, that it is very important to encapsulate code in classes and methods to be able to reuse bits and pieces for other purposes than they were originally made for. The same goes for t-sql development, by using stored procedures and functions. But often you need to slightly chance the result set for your needs, to be able to reuse the data from an existing stored procedure for other purposes. Let me demonstrate how you would usually accomplish this using temp tables:

--Create table to hold test data
CREATE TABLE ResultSetTest (
    Id INT IDENTITY (1, 1),
    SomeText VARCHAR(50),
    SomeDate DATETIME2 DEFAULT SYSDATETIME()
)
GO
--Insert test data
INSERT INTO ResultSetTest (SomeText)
SELECT 'This is just some not so random text'
FROM
    sys.objects t1
    CROSS JOIN sys.objects t2
GO
--Create procedure to fetch data
CREATE PROCEDURE GetData
AS
SET NOCOUNT ON
SELECT Id, SomeText, SomeDate
FROM ResultSetTest
GO

Let’s do a very basic performance analysis of this procedure, by examinating the logical reads it performs:

SET STATISTICS IO ON
EXEC GetData
GO

The message output says:

Table 'ResultSetTest'. Scan count 1, logical reads 33, physical reads 0, read-ahead ...

Now let’s try to create a new stored procedure, that reuses the GetData procedure, but transforms the output:

CREATE PROCEDURE MyNewGetData
AS
SET NOCOUNT ON
CREATE TABLE #ResultSetTest (
    id INT,
    SomeText VARCHAR(50),
    SomeDate DATETIME2
)
--Insert result set from sp into temp table
INSERT INTO #ResultSetTest
EXECUTE GetData
--Return the same columns, but cast the SomeDate column
SELECT
    Id,
    SomeText,
    CAST(SomeDate AS DATETIME) AS SomeDateConverted
FROM #ResultSetTest
DROP TABLE #ResultSetTest
GO

We need to create a temp table that matches the result set from the original procedure. Then we insert the data in the temp table, and finally select and convert the data. This is not pretty at all.

If we execute the new procedure, we get the following IO statistics result:

EXEC MyNewGetData
GO
Table 'ResultSetTest'. Scan count 1, logical reads 33, physical reads 0, read-ahead ...
Table 'Worktable'. Scan count 0, logical reads 4257, physical reads 0, read-ahead ...
Table 'Worktable'. Scan count 1, logical reads 9004, physical reads 0, read-ahead ...
Table 'Worktable'. Scan count 1, logical reads 33, physical reads 0, read-ahead ...

That is a total of 13327 logical reads! That is more than 400 times as many reads as the original stored procedure. We must be able to do better than that, so let’s try the new WITH RESULT SETS feature:

ALTER PROCEDURE MyNewGetData
AS
SET NOCOUNT ON
EXECUTE GetData
WITH RESULT SETS
(
    (
    Id INT,
    SomeText VARCHAR(50),
    SomeDateConverted DATETIME -- Notice the change in data type as well as column name
    )
)
GO
EXEC MyNewGetData
GO
Table 'ResultSetTest'. Scan count 1, logical reads 33, physical reads 0, read-ahead ...

This is more like it. Now we only perform the same 33 logical reads as the original, but we managed to rename and convert the output from the procedure as we wanted. And it is not hard to agree, that by using the WITH RESULT SETS we get a way simpler query that gives us exactly what we wanted.

Unfortunately column renaming and type casting is the only transformation possible at the moment. It would be very nice if it was possible to do the following transformations as well:

  • Add column with default data
    • could be something like: Enabled BIT = 0
  • Exclude columns from output
  • Reorder columns
  • Convert columns by using functions
    • could be something like: SomeDateConverted VARCHAR(50) = CONVERT(VARCHAR(50), SomeDate, 112)

and possibly many others.

Some of these transformation has already been requested in this Microsoft connect ticket, but for now we still need to use the temp table approach to do stuff like that.

So please go ahead and vote for the ticket if you would also like these features added.

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating