What is the main difference between functions and procedures in Oracle?
Why must I use procedures if I can do everything with functions?
If I cannot call procedure in sql statement, ok, I'll write a function to do the same work.
Procedures don't return values, ok, I'll return only sql%rowcount or 1(success), 0(exception) after any dml operation
Both procedures and functions can pass variables to calling environment via OUT/IN OUT parameters
I heard that the main difference is in performance, "procedures are faster than functions", but without any supporting detail.
The difference is- A function must return a value (of any type) by default definition of it, whereas in case of a procedure you need to use parameters like OUT or IN OUT parameters to get the results. You can use a function in a normal SQL where as you cannot use a procedure in SQL statements.
Some Differences between Functions and Procedures
A function always returns a value using the return statement while a procedure may return one or more values through parameters or may not return at all.Although, OUT parameters can still be used in functions, they are not advisable neither are there cases where one might find a need to do so. Using OUT parameter restricts a function from being used in a SQL Statement.
Functions can be used in typical SQL statements like SELECT, INSERT, UPDATE, DELETE, MERGE, while procedures can't.
Functions are normally used for computations where as procedures are normally used for executing business logic.
Oracle provides the provision of creating "Function Based Indexes" to improve the performance of the subsequent SQL statement. This applies when performing the function on an indexed column in where clause of a query.
More Information on Functions Vs. Procedures here and here.
There is almost never a performance difference between procedures and functions.
In a few extremely rare cases:
A procedure IN OUT argument is faster than a function return, when inlining is enabled.
A procedure IN OUT argument is slower than a function return, when inlining is disabled.
Test code
--Run one of these to set optimization level:
--alter session set plsql_optimize_level=0;
--alter session set plsql_optimize_level=1;
--alter session set plsql_optimize_level=2;
--alter session set plsql_optimize_level=3;
--Run this to compare times. Move the comment to enable the procedure or the function.
declare
v_result varchar2(4000);
procedure test_procedure(p_result in out varchar2) is
begin
p_result := '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789';
end;
function test_function return varchar2 is
begin
return '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789';
end;
begin
for i in 1 .. 10000000 loop
--Comment out one of these lines to change the test.
--test_procedure(v_result);
v_result := test_function;
end loop;
end;
/
Results
Inlining enabled: PLSQL_OPTIMIZE_LEVEL = 2 (default) or 3
Function run time in seconds: 2.839, 2.933, 2.979
Procedure run time in seconds: 1.685, 1.700, 1.762
Inlining disabled: PLSQL_OPTIMIZE_LEVEL = 0 or 1
Function run time in seconds: 5.164, 4.967, 5.632
Procedure run time in seconds: 6.1, 6.006, 6.037
The above code is trivial and perhaps subject to other optimizations. But I have seen similar results with production code.
Why the difference doesn't matter
Don't look at the above test and think "a procedure runs twice as fast as a function!". Yes, the overhead of a function is almost twice as much as the overhead of a procedure. But either way, the overhead is irrelevantly small.
The key to database performance is to do as much work as possible in SQL statements, in batches. If a program calls a function or procedure ten million times per second then that program has serious design problems.
State-changing vs non-state-changing
On top of Romo Daneghyan's answer, I've always viewed the difference as their behaviour on the program state. That is, conceptually,
Procedures can change some state, either of the parameters or of the environment (eg, data in tables etc).
Functions do not change state, and you would expect that calling a particular function would not modify any data/state. (Ie, the concept underlying functional programming)
Ie, if you called a function named generateId(...), you'd expect it to only do some computation and return a value. But calling a procedure generateId ..., you might expect it to change values in some tables.
Of course, it seems like in Oracle as well as many languages, this does not apply and is not enforced, so perhaps it's just me.
Procedure may or may not return value but functions return value.
procedure use out parameter returnvalue purpose but function returnstatment provide.
procedure used manipulation of data but function use calculation of data.
procedure execution time not use select statement but function use select statement. These are major difference of it.
This is a great question and as far as I can tell has not really been answered. The question is not "What's the difference between a function and a procedure?" Rather, it is "Why would I ever use a procedure when I can do the same thing with a function?"
I think the real answer is "It's just convention." And as it's convention, it's what other developers are used to and expect, so you should follow the convention. But there is no functional reason to write a subprogram as a procedure over a function. The one exception may be when there are multiple OUT parameters.
In his 6th edition of Oracle PL/SQL Programming, Steven Feuerstein recommends that you reserve OUT and IN OUT parameters for procedures and only return information in functions via the RETURN clause (p. 613). But again, the reason for this is convention. Developers don't expect functions to have OUT parameters.
I've written a longish post here arguing that you should only use a procedure when a function won’t do the job. I personally prefer functions and wish that the convention was to use functions by default, but I think a better practice is to accept the things I cannot change and bow to the actual convention and not the one I would wish for.
i think the major difference is :
Functions can not contain DML Statemnt whereas the procedures can.
for example like Update and Insert.
if i am wrong correct me
As I know, Store procedure is compiled once and can be called again and again without compiled again. But function is compiled each time called. So, Store procedure improves performance than function.
Related
I know that this question is all over..
But Im really struggling to understand,
I see everywhere that functions cannot be used to perform crud operations on the db ( such as update statement ) which is not true.
Other than that, Basically the MAIN difference between them is that a procedure can have in and out parameters 0->n but a function has a return, and does not store the value in an out parameter..
Yea there are some small differences like the way you invoke it, if Im not wrong a function can be called within a select statement whereas a procedure cannot.
So to be honest, I dont really see any difference bewteen those two.
What should I answer if Im asked " Why would you choose function over procedure" ( or the opposite ). THANKS
Well, that's true (except for a typo, here):
function can be called within a select statement whereas a function cannot (bold part should be "procedure")
You'd choose function when there's something you want to return to caller. Use a procedure when you want to process something.
Functions - as you said - can be used in a select statement, which can be used in both SQL and PL/SQL. Procedures, on the other hand, require PL/SQL. It is way simpler to call a function than a procedure (presume f_today and p_today return sysdate; function as return value, procedure via its out parameter), e.g.
select f_today from dual;
than
declare
l_today date;
begin
p_today(l_today);
dbms_output.put_line(l_today);
end;
/
Functions can execute DML operations, but only if they are autonomous transactions. That's not what you'd always want to do. If you want to perform DML, you - usually - pick a procedure.
Although it is possible to do probably everything in both of them, choose the one that is most appropriate for what you are currently doing. Sometimes it is a function, another time it is a procedure (and sometimes you create a function which is then called by the procedure).
It just depends.
Because procedures can have OUT parameters, they too can return a value to the caller. And because functions are internally PL/SQL blocks that can do everything procedures can do, they also process things. And DML is just as possible in either of them.
I think the real difference is that a function must have one and only one main return value (passed back by the RETURN clause), whereas a procedure does not have to return anything, and indeed cannot do so with a RETURN clause. But either can use OUT parameters to pass back information.
Of course only functions can be called in SQL (as opposed to PL/SQL). But besides that, you can pretty much do anything you need with either a function or a procedure. I think it makes good programming sense to use a function when the main point of it is to retrieve a single atomic value, and to use a procedure when the main point is to make changes to the database or there are multiple things that are to be passed back and no one item is conceptually the "main" thing.
However, let me further qualify. In my PL/SQL programming, I tend to use functions more often than procedures even if the main point isn't to get something back, because I nearly always want a return/status code back (success vs. failure), so status is a good "main return value" for just about anything, making functions a good fit. This style of programming handles exceptions close to their source and returns statuses from named functions rather than raising exceptions out of them. But this is only one way to do it. Anyway, I hope this helps.
While learning about OpenEdge Progress-4GL, I stumbled upon running external procedures, and I just read following line of code, describing how to do this:
RUN p-exprc2.p.
For a person with programming experience in C/C++, Java and Delphi, this makes absolutely no sense: in those languages there is a bunch of procedures (functions), present in external files, which need to be imported, something like:
filename "file_with_external_functions.<extension>"
===================================================
int f1 (...){
return ...;
}
int f2 (...){
return ...;
}
filename "general_file_using_the_mentioned_functions.<extension>"
=================================================================
#import file_with_external_functions.<extension>;
...
int calculate_f1_result = f1(...);
int calculate_f2_result = f2(...);
So, in other words: external procedures (functions) mean that you make a list of procedures (functions), you put all of them and in case needed, you import that file and launch the procedure (function) when you need it.
In Progress 4GL, it seems you are launching the entire file!
Although this makes no sense at all in C/C++, Java, Delphi, I believe this means that Progress procedure files (extension "*.p") only should contain one procedure, and the name of the file is then the name of that procedure.
Is that correct and in that case, what's the sense of the PERSISTENT keyword?
Thanks in advance
Dominique
There are a lot of options to the RUN statement: https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref%2Frun-statement.html%23
But, in the simple case, if you just:
RUN name.p.
You are invoking a procedure. It might be internal, "super", "persistent" or external. It could also be an OS DLL.
The interpreter will first search for an internal procedure with that name. Thus:
procedure test.p.
message "yuck".
end.
run test.p.
Will run the internal procedure "test.p". A "local" internal procedure is defined inside the same compilation unit as the RUN statement. (Naming an internal procedure with ".p" is an abomination, don't do it. I'm just showing it to clarify how RUN resolves names.)
If a local internal procedure is not found then the 4gl interpreter will look for a SESSION SUPER procedure with that name. These are instantiated by first running a PERSISTENT procedure.
If no matching internal procedure or SUPER procedure is found the 4gl will search the PROPATH looking for a matching procedure (it will first look for a compiled version ending with .r) and, if found, will RUN that.
There are more complex ways to run procedures using handles and the IN keyword. You can also pass parameters and "compile on the fly" arguments. The documentation above gets into all of that. My answer is just covering a simple RUN name.p.
Progress was originally implemented as a procedural language which did it's thing by running programs. That's what you're seeing with the "run" statement.
If one was to implement this in OO, it'd look something like this:
NEW ProgramName(Constructor,Parameter,List).
Progress added support for OO development which does things in a way you seem more familiar with.
Why is it that CURRENT_DATE, CURRENT_TIMESTAMP, SYSDATE, and SYSTIMESTAMP are called without parentheses. I understand that they take no parameters, but in other languages, you would still call the functions using parentheses. Is it the case in Oracle that any function that never takes parameters cannot be called with parentheses?
If someone could point me to the documentation on this, I'd appreciate it.
Oracle is weird in many ways. It plays fast and loose with lots of things: the meaning of NULL, implicit data type conversions, and a whole number of other things.
Among them, as you noticed, is their inconsistent syntax for calling functions with no parameters. (For declaring such functions, too - see below.)
Native functions like sysdate and current_timestamp, which do not take arguments, must be written without parentheses. You ask for documentation... the most direct (and yet not entirely satisfactory) pointer is to the documentation of each function, where the syntax is shown very clearly without parentheses. What are you looking for - a separate mention in the documentation, where they state this explicitly?
Compare this with analytic functions like rownumber(), for example, which also do not take arguments. You must write them with empty parentheses!
Worse: For functions you write yourself in PL/SQL, and call from SQL statements: if the function takes no arguments, then it must be defined without parentheses. However, when you invoke it (in a select statement, for example) you can call it with or without (empty) parentheses - both syntaxes are valid. Not so, alas, with the native functions, like sysdate. Why? Again, a good question to ask Oracle.
It doesn't end there, either. connect_by_root is a "hierarchical function" (a function that can be used in hierarchical queries). It takes an argument - which can be given in parentheses (as in any normal function) or without parentheses! Go figure.
If you ask WHY??? - you are not alone. I have no clue either.
To further confuse things, some SQL functions have corresponding PL/SQL functions defined in the "STANDARD" PL/SQL package. This allows functions like SYSDATE to be invoked on the right hand side of an assignment statement in a PL/SQL program block. Because the function in the "STANDARD" package is a PL/SQL function (and not an SQL one), it can be invoked with or without parentheses.
DECLARE
x DATE;
BEGIN
x:= SYSDATE(); -- Valid
x:= SYSDATE; -- Also valid
END;
Those are all Pseudocolumns which are used in SQL or PL/SQL statements like columns but they aren't really stored on the disk. They can be thought of as special-purpose data elements within the SQL statements just as if they were part of the table.
A DML statement neither be applied on Pseudocolumns, nor user-defined they are, so they do not need to be considered as standard functions or procedures, and the style is conventionally defined by Oracle, itself.
By the way, this syntax(without parentheses) is valid even for a function in Oracle provided that no needs to have any parameter as
seems more logical rather than what other systems do.
Oracle says : Parameter declarations are optional. Functions that take no parameters are written without parentheses
There is a procedure A with 2 parameters and this procedure is called in 10 stored procedures.(b,c,d....)
Now proc A is updated with 3 parameters , is there any way to update proc A parameters list in calling 10 procs in a single go.
Thanks in advance
Generally, when you publish your API (for example a package specification with several procedures and functions) and it is put into use, you have signed a contract of sorts with other developers.
You should not change the signature of those subprograms (change the terms of the contract) unless absolutely necessary.
Alternatives include:
When adding a new IN parameter, always put it at the end of the existing parameter list and provide a default value that reflects current (pre-change) behavior. All existing invocations of the subprogram remain valid.
If your are adding OUT or IN OUT parameters, consider leaving the current subprogram as is, and instead adding an overloading - same name but with the new, expanded parameter list.
This way, the existing code is not invalidated. You can then notify developers about the new subprograms (change to the contract) and they can choose to use them or not.
You can use PL/Scope, by the way, to find all usages of a particular subprogram. LiveSQL.oracle.com offers a number of PL/Scope scripts. Just search for "scope". Also, Philipp Salvisberg offers a great PL/Scope utility on Github: https://www.salvis.com/blog/2017/03/17/plscope-utils-utilities-for-plscope-in-oracle-database-12-2/
If there is only a few procedures will update 3rd statement, you'd use default value for your parameter. So you dont have to update all 10 procedures.
For ex,
CREATE OR REPLACE PROCEDURE PRC_UPD_MYPROCEDURE
(
p_ParameterOne IN NUMBER,
p_ParameterTwo IN VARCHAR2,
p_ParameterThree IN NUMBER DEFAULT NULL,
)
so when you call your procedure like (without third parameter),
PRC_UPD_MYPROCEDURE(1234,'EXAMPLE');
is valid.
I have two different packages with the same procedures (number and names), but overloaded. In the second package each procedure has one more parameter.
Specifically, in one procedure there are different declarations (cursors, etc), but EXACTLY the same code.
Now, I would like to have that code in one place, so as to maintain it in a single place. How could I do that?
you can have the overloaded procedures in the same package. But if you are asking whether you can have just one procedure rather than replicate the code, the answer is also yes, you can have one procedure with all the parameters, and then check the value of them within the procedure. You can also set a DEFAULT value for each parameter should someone call the procedure without all the require parameters (although this does assume an certain order for the parameters)