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

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.

Related

Why can't we call procedure from sql

I know we can call the function from SQL if it doesn't contain out parameter or DML(except autonomous). But we can't call the procedure from SQL in any condition.
What is the reason for it?
Why can't we call the procedure from SQL? Any specific reason.
The reason is that the SQL ANSII standard specifies that only functions can be used in the SQL query.
ISO committee members did not define the use of procedures in SQL queries.
You can:
call dbms_output.put_line('Hello')
CALL is part of the SQL language.
Or we can embed a procedure in an inline function:
with function f (p varchar2)
return varchar2
as
begin
dbms_output.put_line('Hello');
return p;
end f;
select f('Demo')
from dual
If you mean a SELECT statement specifically, I can't see how you expect that to work. What result set would you expect a query like this to return?
select dbms_output.put_line('Hello')
from dual
or
select dbms_stats.gather_table_stats(user, table_name)
from user_tables
This isn't an arbitrary restriction by some standards committee. It just doesn't make any sense semantically.
You can call or execute a procedure easily in SQL. Both parametrized or non can be called.
EXEC dbo.procedure_name
I'm assuming, that you are asking about calling procedures from within other SQL statements (not just call a procedure on its own, which is obviously possible).
Why? That's a matter of opinion, and you would have to ask Oracle DB architects for a real cause.
It would seem, that introducing procedure calls into all possible SQL statements, would bring both syntax and implementation complexity, while not necessarily bringing much more value. Usually there are alternatives, which are not much harder to use, while allowing the same outcome.
In case of a query (a SELECT statement), the result should be a data set, and no changes in the database state (data or structure) should be done. A PL/SQL procedure does not return a data set, and can change the database state.
If you are in a situation, where the procedure call is needed to prepare the data, you'd like to query, then you have the possibility to call the procedure first, and then query the database.
You can also write a procedure, which will have an output parameter of a cursor reference, which will effectively give you a query result. (For an ad hoc case, you could use parameterized anonymous PL/SQL block.)
You can also write a tabular function, where you can do complex data processing, using PL/SQL, and return a data set. Such function can be used in a query.
If you are asking also about other types of SQL statements, then you can always call DML (INSERT / UPDATE / DELETE / MERGE), DDL (CREATE / ALTER / DROP) or DCL (GRANT / REVOKE) from a procedure or an anonymous PL/SQ block, that does those and allows you to mix PL/SQL logic in. No need to do this the other way (introducing PL/SQL into DML / DDL / DCL).

Run an oracle SQL script twice with different parameters

I have an SQL statement in Oracle SQL developer that has some variables:
DEFINE custom_date = "'22-JUL-2016'" --run1
DEFINE custom_date = "'25-JUL-2016'" --run2
SELECT * FROM TABLE WHERE date=&custom_date
The real query is much more complicated and has many more variables and new tables are created from the results of the query. How can I create a script so that the query is executed twice, the first time with the custom date set as in the first line and the second time as in the second line.
In Oracle, the &variable is a "substitution variable" and is not part of SQL; it is part of the SQL*Plus scripting language (understood by SQL Developer, Toad etc.)
The better option, and what you are asking about, is BIND VARIABLES. The notation is :variable (with a colon : instead of &), for example :custom_date.
The difference is that a substitution variable is replaced by its value in the front-end application (SQL Developer in your case) before the query is ever sent to the Oracle engine proper. A bind variable is substituted at runtime. This has several benefits; discussing them is outside the scope of your question.
When you execute a query with bind variables in SQL Developer, the program will open a window where you enter the desired values for the bind variables. You will have to experiment with that a little bit till you can make it work (for example I never remember if a date must be entered with the single quotes or without). Good luck!
Define is used in TRANSACT SQL. To do this Oracle way, You can create anonymus PL/SQL block, similar to this:
DECLARE
p_param1 DATE;
p_param2 NUMBER;
CURSOR c_cur1(cp_param1 DATE,cp_param2 NUMBER)
IS
SELECT * FROM table WHERE date = cp_param1
;
BEGIN
-- Execute it first time
p_param1 := TO_DATE('2016-09-01','YYYY-MM-DD');
FOR r IN c_cur1(p_param1)
LOOP
NULL;
END LOOP;
-- Execute it second time
p_param1 := TO_DATE('2015-10-11','YYYY-MM-DD');
FOR r IN c_cur1(p_param1)
LOOP
NULL;
END LOOP;
END;
And in it, You create cursor with parameters and execute it twice with different parameter.
I do not know why You want to execute this query twice, so the script abowe does nothing with results, but it certainly should execute Your query twice, with different params.

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.

Oracle SQL Stored Procedures Call vs. Execute

Problem
I'm trying to understand the difference between Oracle SQL commands CALL and EXECUTE.
I've been using CALL to kick off stored procedures but in talking with another developer I found that he almost exclusively uses EXECUTE. I did some research online to see if I was doing something incorrectly but I'm not seeing the clear distinction between the two commands and people seem to use them interchangeably.
Based on the documentation, they seem remarkably similar (at least in terms of interacting with stored procedures).
http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_4008.htm
http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12022.htm
http://docs.oracle.com/cd/B28359_01/olap.111/b28126/dml_app_dbms_aw026.htm
It does look like CALL is a universal SQL command while EXECUTE seems to be proprietary so I would be inclined to use CALL over EXECUTE but then again I don't know what that means in regards to performance.
Questions
Is one preferable over the other in terms of kicking off a stored procedure? Does it matter?
If it does matter, what is a situation where either is appropriate?
Are there any performance differences between the two? What's best practice?
Both EXEC[ute] SP() and CALL SP() could be used in SQL*Plus to execute an SP. BTW, you can also use BEGIN SP(); END;
But there are some differences.
CALL is Oracle SQL and should work everywhere. Other DB clients that can talk to Oracle may or may not support SQL*Plus EXEC. Many do (for example, Oracle SQL Developer, SQLWorkbench/J), but some don't (Liquibase).
The data types of the parameters passed by the CALL statement must be SQL data types. They cannot be PL/SQL-only data types such as BOOLEAN.
EXEC could be used to execute not only an SP, but an arbitrary statement.
If an SP does not have parameters, you can use EXEC SP; syntax, but CALL requires empty parentheses: CALL SP();
If you are calling a proc that returns a sys_refcursor using Toad, there is a difference between CALL and EXEC.
create procedure foo(i in number,o out sys_refcursor)
as
begin
open o for
select i from dual;
end;
exec foo(1,:r); -- outputs 1 row
call foo(1,:r); -- outputs 0 rows
-- Note: when you prefix a parameter with a colon, Toad will prompt you for the type (which in this case is a cursor).

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).