Using output from Procedure in another Procedure in Oracle SQL - 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.

Related

Execute Store Procedure For All Rows in SELECT without using Cursor

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

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.

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.

How to convert a big set of SQL queries into a single stored procedure that uses a variable?

I am trying to convert a big list of SQL statements into a PostgreSQL stored procedure that uses a variable, one that should be populated from the result of one SELECT.
If you want to see what has to be run, you can check it here
As far as I know PostgreSQL does not allow use to use variables inside stored procedures that are using SQL language, so I'm looking for solutions that would require a minimal number of changes.
It's much easier after you find the right syntax:
Here is the procedure definition for plpgsql language:
DECLARE myvar integer;
BEGIN
SELECT INTO myvar FROM ...;
-- use myvar
END;
The code seems to be pretty repetitive. Will EXECUTE be of any help? (manual about execute) (example and more information) It allows you to run predefined queries and create new ones on the fly.

Stored procedure with output parameters vs. table-valued function?

Which approach is better to use if I need a member (sp or func) returning 2 parameters:
CREATE PROCEDURE Test
#in INT,
#outID INT OUT,
#amount DECIMAL OUT
AS
BEGIN
...
END
or
CREATE FUNCTION Test
(
#in INT
)
RETURNS #ret TABLE (outID INT, amount DECIMAL)
AS
BEGIN
...
END
What are pros and cons of each approach considering that the result will passed to another stored procedure:
EXEC Foobar #outID, #outAmount
A table valued function can only be used within a scope of a single SELECT statement. It cannot perform DML, catch exceptions etc.
On the other hand, it can return a set which can immediately be joined with another recordset in the same query.
If you use DML or don't need to use the output parameters in the set-based statements, use a stored proc; otherwise create a TVF.
A stored procedure that calls a function :-) I think either will suite you... if your app uses stored procedures for querying the database, then it may be best to be consistent... if you use an ORM, it may not recognize the function... I don't think you can go wrong with either.
In one of my apps, we preferred using the function approach, to throw in another perspective.
HTH.
With the stored procedure using output parameters you will only be able to return the two values: #outID and #amount.
With the table-valued function, you will be able to return a whole set of (outID, amount) tuples. In addition, a table-valued function can be used wherever table or view expressions are allowed in queries, such as:
SELECT dbo.Test(1) AS TestValues
I would argue The output parameter approach is most desirable. This makes it more self documenting that not more than one tuple is expected and I would assume is likely to be more efficient.
I would only use a table-valued function if I needed to obtain a table of values.
If there is only one "row" in your output then it would be preferable to use output parameters in a Stored Procedure.
One exception to this is if your SP/UDF can be written as a single SELECT statement - i.e. an Inline Function - because SQL Server can make better optimizations if you ever need to do something like join it to the output of another query. You may not be doing that now, but writing an inline UDF means you won't be caught off-guard with slow-as-molasses queries and timeout reports if somebody starts using it that way in the future.
If none of that applies to you then I would use a Stored Procedure for the reasons outlined; you don't want to create the illusion of set-based semantics when you aren't actually supporting them.
Output parameters.
Multi-statement table value functions are difficult to trace and tune. Stick with the stored procedure which is easier to troubleshoot.
Also, you are limited to what you can do in a udf. Say you need to add logging, or call an extended stored proc later... you can't use a udf for this.
I think your better bet would be the SP because with the TBF (table value function) you'd have to iterate through the table to get your value.
Bear in mind that if you iterate through the table in SQL, then you'll need to use a CURSOR (which aren't too bad, but can be a little tricky to use).