These components have the ability to retrieve multiple result sets (e.g. from a stored proc) in one go, and using D5 I can successfully use NextRecordSet to get at the second and subsequent ones from a Sql Server.
However, this only works if I specify the cursor location as clClient; if I use clServer, I get a "Does not return multiple result sets" error. Is this an inherent limitation (e.g imposed by the MDac layer on the client) or can multiple recordsets be successfully retrieved from a server-side cursor?
It is an inherent limitation to server side cursors. As stated in following MSDN link:
Server cursors cannot be used with statements that generate more than
one recordset.
This restriction applies to all statements described in Generating
Multiple Recordsets. For more information, see Generating Multiple
Recordsets. If a server cursor is used with any statement that
generates multiple recordsets, an application can return one of the
following errors:
Cannot open a cursor on a stored procedure that has anything other than a single SELECT statement in it.
sp_cursoropen. The statement parameter can only be a single SELECT statement or stored procedure.
Related
I am currently working with a stored procedure that performs some background processes and then returns one of two results tables.
If it works ok I get a one column table that says success, if it doesn't then I get a four column table with various error data.
While this is fine if you just execute the code from .net, I now need to execute this from within another stored procedure. While I don't need the output, I do need the background processes to take place. I'd usually insert the output into a table, but can't in this case as the columns in the output varies dependent on the result, and as such cannot define a table that it can insert into.
Easiest answer would be to rewrite the outputs of the background SP to be consistent but this isn't an option. I've even tried wrapping this inside a UDF but the stored procedure can't be called from with a function.
Whatever solution I finally use it must work on versions from SQL Server 2008 R2 up to 2016.
Does anybody have any suggestions?
Many thanks,
Mat.
I would image you could create a SP that inserts the result of the inner SP into a temporary table using the hack below.
Insert results of a stored procedure into a temporary table
If that blocks the ouput then you can return no data.
So, similar to "SQL Server compare results of two queries that should be identical", I need to compare the output of two stored procedures to ensure the new version is generating equivalent output to the old version. The tricky part is that my SP outputs six tables of differing widths.
I started writing a hybrid version of them that would compare each of the tables individually, but it's a pretty complex SP, so I was hoping there was an easier way.
I tried using EXCEPT as in the linked question, but it looks like that will only compare one table to one other table.
Easy option 1: Output the stored procedure results to a text file (one per procedure version) and use a diff tool/editor to make sure they are the same.
Easy option 2: Write the stored procedure results to a table/temp table (per return table per procedure) and write sql to compare the results. Just count the rows in each result table and then do a count of the union (not union all) of both tables. Repeat for each result table.
You can capture multiple result sets in .NET (C# or VB) quite easily. You can create a DataAdapter and DataSet, and use the DataAdapter.Fill() method to populate the DataSet. Each result set will be stored as a DataTable within that DataSet. Then you just need to loop through the DataTables collection in each DataSet and compare them. You can find more info on this MSDN page: Populating a DataSet from a DataAdapter
This can be done in either SQLCLR if you want to run it as a stored procedure or user-defined function, OR it can be a stand-alone console application. Running it as a SQLCLR stored procedure is quite convenient, but given that you will be stored all results for all 6 result sets, and for both stored procedures that you are testing, that might require too much memory. In that case, the console app is the the way to go.
The only thing I can think of is add an additional parameter to your both of (New/old) stored procedures to handle which result it should return like.
Exec usp_proc #var1 , #var2 , #ResultSet = 1
The above execution should return the first result set and if you pass #ResultSet = 2 it should return second result set and so on.....
do this with both stored procedure and then compare the result sets group by group (using except will do the trick).
I have an SSIS package with a data flow task. The OLE DB source has an execute proc statement. It fails while saving with below error message.
an OLEDB record is available... The metadata could not be determined because the statement 'select appname....' in procedure is not compatible with the statement 'select appid....' in procedure
This proc has several select statements and returns the appropriate result set as per parameters passed. Any pointers to bypass this error?
So you're saying that the SP will return different meta data depending on the parameter passed? SSIS doesn't like this - it can't update the meta data dynamically at run time. i.e. if you create a package that splits or sorts on a certain column, then you run the SP and it doesn't return that column, or the same column is a different data type, what should SSIS do? It can't automatically work it out.
I suggest you create a data source for each possibility of result set returned and conditionally execute each on as required.
In short SP's returning optionally different datasets is often not a good idea, definitely not from an ETL perspective.
Here is some code that shows how to create dynamically built output, (you could use the same method with just one output), but you'll still face the same problems downstream.
http://www.codeproject.com/Articles/32151/How-to-Use-a-Multi-Result-Set-Stored-Procedure-in
I ran into this issue as well. In my case, the result returned looked identical no matter which branch was executed, the difference was just in how that result was obtained (including different source tables). I simply executed all the cases with a union, and each "where" clause included the conditions for its execution instead of using "if" logic to choose a query.
All,
Architecture for crystal report,
I have two option,
Stored procedure with business logic and display data on crystal report.( tight coupled)
as SP are specially designed for the reports - less reusable. but recompiled.
Views to pull data and add business logic on report itself to filter data.(loose coupled)
-reusable views but what about performance compared to SP?
Any suggestions are more welcome...
If I understand your question correctly, I would recommend implementing option 1.
By calling a stored procedure, you will be reducing network traffic because you'd be passing only parameter definitions and the procedure name, instead of the entire query string you'd be sending to the DB in option 2.
Using stored procedures also keeps the plan cache tidy by compiling the set of SQL statements within the stored procedure, instead of storing separate plans for each statement within the string you'd be passing to the DB in option 2.
I'm trying to build a designer in .NET, and would like to be able to retrieve the columns and column types of the output from a stored procedure without calling it so the designer can be used to map the output. Is this possible? I'm even willing to use an unmanaged API if necessary.
I believe what you're looking for is SET FMTONLY (Documentation).
This allows you to execute a SP (or select statement) and see what columns would be returned without actually executing the query.
This isn't possible, in general, because even a single stored procedure can return different result sets, with different columns or column data types.
In extreme cases even the number of returned result sets may depend on parameters and when the stored procedure uses dynamic sql its definitely impossible.