Reputation: 1373
I'm trying to port oracle stored procedures (plsql) to a postgresql function (pl/pgsql).
In oracle I can define a stored procedure with IN and OUT parameters.
CREATE OR REPLACE PROCEDURE MY_TEST(foo IN NUMBER,
bar OUT NUMBER)
IS
BEGIN
bar := 1
END
This will store a value of 1 in the variable that is passed to the stored procedure. I can call it as follows:
DECLARE
outValue NUMBER ;
BEGIN
Exec MY_TEST(10, outValue);
DBMS_OUTPUT.PUT_LINE('Value Returned Is : '||outValue) ;
END ;
In Postgresql (pl/pgsql) I can define a function like this one:
CREATE OR REPLACE FUNCTION MY_TEST(foo IN NUMBER,
bar OUT NUMBER)
BEGIN
bar := 1
END;
$body$
LANGUAGE PLPGSQL;
However I can not use the out parameter the same way as I could in oracle. In postgresql the OUT parameter defines the return value. In oracle stored procedures don't have return values, but instead write the output into the variable that is passed in the call
Is there something I overlooked, that would permit me to use pl/pgsql functions in a similar way as the stored procedure is used in the example above?
Any hints are greatly appreciated.
Upvotes: 1
Views: 5359
Reputation: 656814
In PostgreSQL, PL/pgSQL or SQL functions take parameter values and return values.
They do not take pointers or references - so that the value of the referenced address could be manipulated.
You could do something like that in theory with a C-language function, where you can pass values by reference. However, de facto, you cannot. The manual warns:
Never modify the contents of a pass-by-reference input value. If you do so you are likely to corrupt on-disk data, since the pointer you are given might point directly into a disk buffer. The sole exception to this rule is explained in Section 35.10.
In short: what you are trying to do is impossible in PostgreSQL.
Upvotes: 1
Reputation: 30324
Take a read of this.
http://www.postgresonline.com/journal/archives/129-Use-of-OUT-and-INOUT-Parameters.html
In summary given the following stored function and the anonymous block to test this is one approach that the article will show.
CREATE OR REPLACE FUNCTION fn_plpgsqltestout(param_subject text,
OUT subject_scramble text, OUT subject_char text)
AS
$$
BEGIN
subject_scramble := substring($1, 1,CAST(random()*length($1) As integer));
subject_char := substring($1, 1,1);
END;
$$
LANGUAGE 'plpgsql' VOLATILE;
DO $body$
DECLARE
o_subject_scramble TEXT;
o_subject_char TEXT;
begin
--Option1
SELECT (fn_plpgsqltestout('This is a test subject')).* INTO o_subject_scramble,o_subject_char;
--Option2
SELECT (fn_plpgsqltestout('This is a test subject')).subject_scramble INTO o_subject_scramble;
SELECT (fn_plpgsqltestout('This is a test subject')).subject_char INTO o_subject_char;
--Option3
o_subject_scramble := (fn_plpgsqltestout('This is a test subject')).subject_scramble;
o_subject_char := (fn_plpgsqltestout('This is a test subject')).subject_char;
raise notice 'Return value is: %', o_subject_scramble;
raise notice 'Return value is: %', o_subject_char;
end;
$body$
Upvotes: 0
Reputation:
You don't need an OUT parameter for Postgres:
CREATE OR REPLACE FUNCTION MY_TEST(foo IN integer)
returns integer
as
$body$
BEGIN
return 1;
END;
$body$
LANGUAGE PLPGSQL;
Then use it like this:
DO $body$
DECLARE
result integer;
begin
result := my_test(42);
raise notice 'Return value is: %', result;
end;
$body$
Upvotes: 0