Execute Store Procedure For All Rows in SELECT without using Cursor - sql

I have an SQL that returns n rows like,
SELECT * FROM TABLE
For each row, I wanna execute a stored procedure. I know I can use cursor but I wanna avoid cursor? Is it possible?

You only have a couple of choices. Either modify your procedure to receive a table valued function so you can deal with it set based. Or you are stuck doing some sort of looping, most likely a cursor.

Difficult to answer because you don't say exactly what you are trying to achieve with the stored procedure, but it's possible that you might be able to use a stored function instead of a stored procedure.
https://learn.microsoft.com/en-us/sql/relational-databases/user-defined-functions/create-user-defined-functions-database-engine?view=sql-server-2017

Related

Return table from stored procedure / function after doing merge function SQL Server

I have a stored procedure that takes one table, and doing merge to another table. I want to get a table of logs with the data of what happened to each row, without inserting the data to a table.
I understand a stored procedure cannot return a table, and therefore I thought about using a function, but as of my understanding a function can not make transformations on tables.
Is combining a stored procedure with a function the solution? Or is there any thing else that I am not aware of?
A stored procedure can certainly return a result set, which the client can consume directly just like a regular SELECT statement.
That said, there are a range of options, none of which are perfect. Each suits a different scenario, and are described at length by Erland Sommarskog in How to Share Data between Stored Procedures:
Table-valued Functions
Inline Functions
Multi-statement Functions
Using a Table
Sharing a Temp Table
Process-keyed Table
INSERT-EXEC
Using SQLCLR
OPENQUERY
XML
Cursor Variables
For example, you may not wish to use a permanent table, but a temporary table created by the client and populated by the stored procedure can work well, if directly consuming the results of a SELECT inside the procedure is not suitable.

How to suppress record sets returned by SELECT statements in a Stored Procedure

I'm writing a stored procedure which checks for the existence of various tables in various databases, as well as the permissions that the user executing the stored procedure has on those tables. The stored procedure itself resides within a user database (i.e. it's not in the Master db).
To perform my checks, my stored procedure contains lots of SELECT statements. Each of those obviously returns a record set. What I would like is to somehow suppress these record sets so that they are not returned by the stored procedure, and instead return my own, single record set which is just a collection of messages relating to each check the stored procedure performs.
I think the obvious answer is to use a table-valued function instead, but I've not been able to recreate my tests successfully in a Function as they appear in the stored procedure. For starters, I'm having to use temporary tables (not possible in a function) and dynamic SQL (not very compatible with table parameters).
I think I've basically got two choices:
Rewrite my stored procedure as a function and figure out how to do the checks a different way.
Continue using my stored procedure and use an OUTPUT parameter to return my result messages, probably as a delimited string, and in the associated ASP.NET application just ignore all the record sets the stored procedure returns .
Neither of these solutions is very satisfactory. Before I spend any more time pursuing either one, is there a way to discard the record sets produced by the SELECT statements in a stored procedure and explicitly define what record I want it to return?
Hmm, I only can speculate here...
Are you using something like
SELECT ...;
IF ##rowcount > 0
BEGIN
...
END;
?
Then you can rewrite it using something like
IF EXISTS (SELECT ...)
BEGIN
...
END;
or
DECLARE #variable integer;
SELECT #variable = count(*) ...;
IF #variable > 0
BEGIN
...
END;
In general point the results of your queries to a target (variable, table, expression, ...), then they don't get outputted.
And then just execute the query for your desired result in the end.
In my opinion, here is almost no reason to have stored procedures produce record sets. That is what stored functions are for. On occasion, it is needed, because of the use of dynamic SQL or other stored procedures, but not as a general practice. Much, much too often, I see stored procedures being used where stored functions or views are more appropriate.
What should you do? Even SELECT statement in the stored procedure should be one of the following:
Setting (local) variables.
Saving the results in a temporary table or table variable.
The logic for the stored procedure should be working on the local variables. The results should be returned using OUTPUT parameters.
If you need to return rows in a tabular format, you can do that using tables explicitly (such as a global temporary table or real table). Or, you can have one SELECT at the end that does return a single result set. However, if you need this and can phrase the stored procedure as a function, that is better in my opinion.

Using output from Procedure in another Procedure in Oracle SQL

I have a procedure that looks like this:
create or replace procedure proc1 (prc out sys_refcursor, <filter variables>)
as
begin
open prc for (select * from blah blah blah.. <logic using filter variables,
calculations,etc>
end proc1
I was wondering if it is possible to use the output from this procedure in another procedure to further filter the data I am looking at and do more calculations. Is there a way to pass the sys_refcursor to another procedure and select into that (probably a bad idea)? Or would a temporary table help here?
I understand that I could make this into one procedure but I need the data from both separately as they are both relevant to what I am doing.
Once you wrapped your result set in a cursor, your sql options are limited. You can of course pass the cursor to another function and fetch from it there. But you'll have to do all the dirty filtering work yourself.
Still passing cursors around is sometimes a valid design pattern. Typicall you will fetch from the cursor and generate other selects from that. However, in your case you want to further filter your data, and in this case a cursor is not a good choice in general, because you loose the power of SQL.
If you really want to do such a thing you can use pipelined functions. In contrast to cursors these allow you to create a (virtual) table where you can use plain old select again. And of course you can create such a pipelined function when given a cursor by fetching from it and invoking pipe row repeatedly.
But all of this is tedious and requires quite some boilerplate code.
In general there is not much penaltly in just writing multiple selects with different where clauses. If you want to explicitly encode that these selects are restriciting the result set more and more, use select from select, maybe placing the inner selects into a view, thus creating a hierarchy of views.

How to supply values to sproc from table?

I need to insert values from a table into a sproc. For example:
exec mysproc #param1='col1', #param2='col2'
This can be done using a cursor but is there some way to do it via a set operation?
It is not possible to invoke an sproc as part of a "set operation". Probably, the reason for that is that the sproc might have arbitrary side-effects like modifying data, sending additional result sets (!) or shutting down the server.
A cursor is the canonical approach to this. (Alas.)
You could modify the sproc to take a TVP, of course. Not sure if that is workable for you.
I imagine that the method you choose would be based on the amount of time you have available and it's difficult to say which of these methods is most time consuming without being more intimate with the logic.
There are a few approaches to this problem.
As Robert Harvey has alluded to, you should maybe look at maybe
modifying the proc to accept a table valued parameter (if you are
using SQL Server 2008 upwards). If not, you could create a scalar
XML parameter that is "decoded" in to a table inside the proc.
Populate a #table with your "parameter data" and a ROW_NUMBER() and
use a WHILE loop to call the proc for each row in your #table.
Create a CURSOR (I hate giving CURSOR advice) of type FAST_FORWARD
and iteratively call the procedure.
Dynamic SQL; build up a SQL command string using EXEC or preferably
SP_EXECUTESQL.
My opinion is that first prize would be to re-engineer the proc to
accept parameter filters. Going on the assumption that the dataset
you wish to create parameters from is the result of a filtered
query:
SELECT Moo, Meow
FROM Woof
WHERE Fu = #ParmX
AND Bar = #ParmY
Your proc should be called with #ParmX, #ParmY and the logic inside would then proceed in a set based manner.

SQL Server: Load stored procedure results into table

I have a stored Procedure that returns multiple resultsets(to be specific three resultsets). I just need the first resultset. I am calling the original procedure from a different procedure where i will store the returned resultset into a #table and use it from my further processing.
Also, i can not modify the original stored procedure to achieve this.
Please help!
It's not possible to retrieve the second or further result set from a stored procedure inside SQL.
Two workarounds:
A scheduled job (like a C# program) that periodically calls the stored procedure and stores the result in tables that other procedures can use.
A SQL CLR stored procedure that does the same. The advantage of a SQL CLR procedure is that you can call it from normal SQL stored procedures, so you don't have to wait for the scheduled task.
I haven't tested this, but a work around would be to use OpenQuery and call your SP using it because "Although the query may return multiple result sets, OPENQUERY returns only the first one". OPENROWSET will also do the same...