5

I am using SSIS 2016. I need to execute a stored procedure that returns 4 result sets. I only need to keep the first result set and write this to a table. I can not modify the stored procedure. I do not care about any of the data returned in the other result sets. The stored procedure is in a SQL Server 2016 database. Results will also reside in SQL Server 2016.

I currently have this process running in SSIS 2008 using the "SQL Command" data access mode in an OLE DB Source like below. I have this in a For Each Loop Container to pass a series of param values to the stored procedure as I execute it multiple times for different param values on a daily basis.

SET FMTONLY OFF;

EXEC myProc
     @Param1 = ?,
     @Param2 =?,
     @Param3 = ?;

By default SSIS 2008 is only returning the first result set, which has worked for me as I only care about the first result set.

I am using the Native OLEDB SQL Server client. From what I have read, it has changed the way it handles multiple result sets. I have used the WITH RESULT SETS to define the first result set but if I execute SSIS will fail indicating other result sets need to be defined.

In short, what is the best approach to duplicate what works in SSIS 2008 in SSIS 2016?

Hadi
  • 36,233
  • 13
  • 65
  • 124
Chris
  • 53
  • 1
  • 4

3 Answers3

3

Solution Overview

I made 2 Experiments on that issue, the first experiments showed that in case of stored procedures with no parameters, nothing changed in SQL Server 2016 and SSIS 2016, the first Result Set is returned and others are ignored.

The second experiment showed that when using parameters, this will throw an exception, so you have to define metadata using WITH RESULT SETS option, then remove this option.


Detailed Solution

Experiment 1

The following experiment are made using SQL Server 2016 and Visual Studio 2015 with SSDT 2016

  1. First i created this stored procedure

    CREATE PROCEDURE sp_Test
    
    
    AS
    BEGIN
    
    SET NOCOUNT ON;
    
    SELECT TOP 10 PersonType,NameStyle,Title 
      FROM [AdventureWorks2016CTP3].[Person].[Person]
    
    SELECT  TOP 10 PersonType,Firstname,Lastname
      FROM [AdventureWorks2016CTP3].[Person].[Person_json]
    END
    GO
    
  2. Then i added a Data flow task to SSIS package
  3. Added an OLEDB Source, Recordset destination
  4. In OLEDB source i select the Data access mode to SQL command
  5. an use the following commnad

    EXEC sp_Test
    

enter image description here

  1. When clicking on Columns Tab it shows the first ResultSet structure

enter image description here

  1. And we i executed the package it runs succesfully

enter image description here

Experiment 2

I changed the stored procedures to the following:

ALTER PROCEDURE [dbo].[sp_Test]

    @param1 varchar(10),
    @param2 varchar(10),
    @param3 varchar(10)
AS
BEGIN

    SET NOCOUNT ON;


    SELECT TOP 10 PersonType,NameStyle,Title ,@param2 as 'Param'
  FROM [AdventureWorks2016CTP3].[Person].[Person]


    SELECT  TOP 10 PersonType,Firstname,Lastname,@param3 as 'Param'
  FROM [AdventureWorks2016CTP3].[Person].[Person_json]
END

And i used the following SQL Command in the OLEDB Source:

EXEC sp_Test ?,?,?

WITH RESULT SETS (
(
    PersonType NVarchar(10),
    NameStyle NVarchar(10),
    Title  NVarchar(10),
    Param Varchar(10)
)
)

And i mapped the parameters correctly.

enter image description here

enter image description here

When running the package it throws the following exception.

[OLE DB Source 2] Error: SSIS Error Code DTS_E_OLEDBERROR. An OLE DB error has occurred. Error code: 0x80040E14. An OLE DB record is available. Source: "Microsoft SQL Server Native Client 11.0" Hresult: 0x80040E14 Description: "EXECUTE statement failed because its WITH RESULT SETS clause specified 1 result set(s), and the statement tried to send more result sets than this.".

After that i tried to remove the With RESULT SETS option, so the command is :

EXEC sp_Test ?,?,?

I tried to execute the package again, so it is executed with no errors.

Conclusion

Try to use the WITH RESULT SETs option to define the OLEDB Source metadata, after that the metadata is defined, just remove this option and run the package, so it will just take the first Result Set succesfully.

Hadi
  • 36,233
  • 13
  • 65
  • 124
  • The way you are executing your proc does work as I tried the same exact thing. However, this is not how my problem proc is being executed. It has 3 input parameters defined that get populated via a For Each Loop. In my original post I show how its defined. I get an error: "The meta data could not be determined....". If I add a WITH RESULTS SET and define the result set, it will create the columns but then on execution it will fail saying there are multiple result sets. – Chris Jan 03 '18 at 21:15
  • @Chris you have to post these details in your question to b e more clear – Hadi Jan 03 '18 at 21:19
  • @Chris try using data access mode `SQL Command from Variable`, and use a Variable that have the following expression `"EXEC myProc @Param1 = " + @[User::Param1] + ", @Param2 = " + @[User::Param2] + ", @Param3 = " + @[User::Param3] + ";"` – Hadi Jan 03 '18 at 21:26
  • @CHris also change `Delay Validation` property to `True` for the `DataFlow Task` – Hadi Jan 03 '18 at 21:28
  • @Hadi...thanks for the help. I had already tried that Command from a Variable in the same way. I got the same issues with multiple result sets. – Chris Jan 03 '18 at 21:29
  • @Chris if the parameters values changes the first resultset structure changes at well? – Hadi Jan 03 '18 at 21:31
  • @Chris also have you tried `WITH RESULT SETS UNDEFINED` – Hadi Jan 03 '18 at 21:37
  • @Haid...result set structure does not change. The 3 params are a "start date", "end date" (both stay same thru execution) and the 3rd param is just a list of "location codes" that the proc needs to execute for each. The WITH Result Set Undefined command makes no difference. Nor does the Delay. – Chris Jan 03 '18 at 21:53
  • Why using `SET FMTONLY OFF;` try removing it? Also the mystery is that i tried OLEDB Source with parameters and it worked fine!! – Hadi Jan 03 '18 at 21:56
  • SET FMTONLY OFF was required with SSIS 2008. I had removed that and it did not improve anything. The proc I am calling is rather complex as it calls multiple functions based on param values. I have no control over this proc as its in a 3rd party software product. – Chris Jan 03 '18 at 22:02
  • @Chris i made a new experiment and it worked fine, just check my answer update *(experiment 2)* it may leads you to the solution. Hope that this make a sense. If you find this helpful give me a reply or just upvote the answer. Good Luck – Hadi Jan 07 '18 at 14:17
  • @Hadi...I had tried your second approach but as soon as I remove the WITH RESULTS SET statement and try to close the OLE DB Source Editor I get the same meta data error. – Chris Jan 08 '18 at 15:17
  • @Hadi...if you change your proc to include a IF...ELSE on a param value you should then see the same behavior I am. – Chris Jan 08 '18 at 16:37
  • @Chris when introducing IF...ELSE logic the metadata cannot be defined, because it may vary based on condition (even if logically). The SSIS cannot handle this type of OLEDB Source, because when using `WITH RESULT SETS` you are assuming that you need to get all result sets, and without it metadata cannot be predicted because IF..ELSE – Hadi Jan 08 '18 at 21:41
  • @Chris after googling the only way is to alter the procedure, in your case i don't think you will find a solution. Good Luck. – Hadi Jan 08 '18 at 21:42
  • 1
    @Hadi...I figured out the solution (at least for one of my stored procedures)...if I define all the result sets the proc produces, SSIS "ignores" all but the first result set, which is what I need it to do. Sounds like it should have been an obvious thing I should have tried initially but...anyway, thanks for all the efforts. I might not have tried this if nor for your suggestion to define it, run it, then remove it. – Chris Jan 09 '18 at 15:41
0

I know it's not exactly what you are asking for, but maybe you could create another stored proc that will return only the first result set for you? (Without touching the first stored proc.) Or insert the data into a table for you and then you just read the data?

Danielle Paquette-Harvey
  • 1,691
  • 1
  • 16
  • 31
0

If defining result sets, you have to define every result set something like this:

Exec sp_procedure @parm1, @parm2
  with result sets (
    ( text nvarchar(10),
      number int,
      otherNumber int ),
    ( text2 nvarchar(10),
      number2 int,
      decimalNumber float) 
  )
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77