Handling EXCEPTION and return result from function - postgresql

This is my code
CREATE OR REPLACE FUNCTION test_excep (arg INTEGER) RETURNS INTEGER
AS $$
DECLARE res INTEGER;
BEGIN
res := 100 / arg;
BEGIN
EXCEPTION
WHEN division_by_zero
THEN RETURN 999;
END;
RETURN res;
END;
$$
LANGUAGE plpgsql;
That is, I need returned "999", if happened division by zero, but this: SELECT test_excep(0)
returns error: division by zero
CONTEXT: PL/pgSQL function test_excep(integer) line 4 at assignment
What is wrong in my code?

The EXCEPTION clause needs to be in the same block as the exception.
For instance:
CREATE OR REPLACE FUNCTION test_excep (arg integer)
RETURNS integer
AS
$func$
DECLARE
res INTEGER;
BEGIN
res := 100 / arg;
RETURN res;
EXCEPTION
WHEN division_by_zero
THEN RETURN 999;
END
$func$
LANGUAGE plpgsql;

Here is a correct function:
CREATE OR REPLACE FUNCTION test_excep (arg INTEGER) RETURNS INTEGER
AS $$
DECLARE res INTEGER;
BEGIN
res := 100 / arg;
RETURN res;
EXCEPTION
WHEN division_by_zero
THEN RETURN 999;
END;
$$
LANGUAGE plpgsql;
EXCEPTION part must be inside the block where the exception is, and also must be the last part of the block.

Related

postgreSQL : oracle sqlerrm equivalent of postgres

I'm new to PostgreSQL. I have experience in oracle. In oracle , to find the exact error, I use code 'dbms_output.put_line(sqlerrm)' . Here I have a postgresql function returning an integer value
CREATE OR REPLACE FUNCTION public.fn_sqltest(
p_id integer)
RETURNS integer
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
Declare
n integer;
begin
select off_id into n from office
where per_id=p_id;
return n ;
exception when others then
return -1;
end;
$BODY$;
ALTER FUNCTION public.fn_sqltest(character varying)
OWNER TO postgres;
I call this function as below
DO $$
DECLARE
ae integer;
BEGIN
ae:=fn_sqltest(10);
RAISE NOTICE 'exception: % % ', sqlstate , sqlerrm ;
RAISE NOTICE 'Return value is: % ', ae;
END $$;
and I get the error
ERROR: column "sqlstate" does not exist
How can I show the exact error message like sqlerrm in oracle.
I updated the function and wrote a code in function exception section
CREATE OR REPLACE FUNCTION public.fn_sqltest(
p_id integer)
RETURNS integer
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
Declare
n integer;
text_var1 text;
text_var2 text;
text_var3 text;
begin
select off_id into n from office
where per_id=p_id;
return n ;
exception when others then
GET STACKED DIAGNOSTICS text_var1 = MESSAGE_TEXT,
text_var2 = PG_EXCEPTION_DETAIL,
text_var3 = PG_EXCEPTION_HINT;
RAISE NOTICE 'Return value is: % % %',text_var1 , text_var2, text_var3;
return -1;
end;
$BODY$;
ALTER FUNCTION public.fn_sqltest(character varying)
OWNER TO postgres;
Another method is by changing the return type. I changed the return type to text and rewrite the exception section code as below
return sqlerrm;
Unlike PL/SQL, in PL/pgSQL SQLSTATE and SQLERRM are not defined outside an exception handler. See the documentation, section "Obtaining Information About An Error".
This also means that you can't get SQLSTATE and SQLERRM of a successful operation, unlike PL/SQL.
So, if you want to use these special variables outside an exception handler, you have to store them in variables.
I don't know how would you like to return them from the function. I can demonstrate this idea inside your function code:
CREATE OR REPLACE FUNCTION public.fn_sqltest(
p_id integer)
RETURNS integer
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
Declare
n integer;
v_sqlerrm text;
v_sqlstate text;
begin
begin
select off_id into n from office
where per_id=p_id;
return n ;
exception when others then
v_sqlerrm := sqlerrm;
v_sqlstate := sqlstate;
end;
RAISE NOTICE 'exception: % % ', v_sqlstate , v_sqlerrm ;
return -1;
end;
$BODY$;
I know this is old but just for the record: The easiest way to output the state and message of error is to raise them from within the exception clause. You don't need to declare extra variables.
CREATE OR REPLACE FUNCTION fn_sqltest(p_id integer)
RETURNS integer
AS $$
DECLARE
n integer;
BEGIN
SELECT off_id
INTO n
FROM office
WHERE per_id = p_id;
RETURN n;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'exception: % - %', SQLSTATE, SQLERRM;
RETURN -1;
END;
$$ LANGUAGE plpgsql;

How to do a simple array search in PL/pgSQL

I need to know if an integer exists in an array of integers.
Here's what I have:
CREATE OR REPLACE FUNCTION mytest1 () RETURNS integer
LANGUAGE plpgsql
AS $fun$
DECLARE
testid INTEGER := 22;
testary INTEGER [] := '{1,2,3}';
BEGIN
PERFORM testid = ANY (testary);
IF FOUND THEN
RAISE NOTICE '############### found:';
END IF;
RETURN 1;
END;
$fun$
It always returns true. This should be so simple I feel ashamed asking for help. What am I doing wrong?
This is how you can resolve the issue:
CREATE OR REPLACE FUNCTION mytest1 () RETURNS integer
LANGUAGE plpgsql
AS $fun$
DECLARE
testid INTEGER := 1;
testary INTEGER [] := '{1,2,3}';
BEGIN
IF testid = ANY (testary::INTEGER[]) THEN
RETURN 1;
END IF;
RETURN 0;
END;
$fun$;
SELECT mytest1();
Can be simpler, yet:
CREATE OR REPLACE FUNCTION mytest1()
RETURNS boolean AS
$func$
DECLARE
testid int := 1;
testary int[] := '{1,2,3}';
BEGIN
RETURN (testid = ANY(testary));
END
$func$ LANGUAGE plpgsql IMMUTABLE;
The expression returns a boolean value which can be returned directly.

plpgsql function return another function value

I have a function func1() which returns integer.
I want to write another function func2(mode integer) which can return func1() reults or do some more stuff. The return value of func1() is of type INTEGER.
something like this:
CREATE OR REPLACE FUNCTION func2(mode integer)
RETURNS integer AS
$$
begin
if mode=1 then
return func1(); -- NOT plpgsql syntax
end if;
more stuff .....
return 2;
end
$$
LANGUAGE plpgsql VOLATILE
my question is how to do return func1(); ?
I know I can do :
select func1() into temp;
return temp;
but I was wondring if there is a more elegent way to do that.
All of these work:
Option 1:
CREATE OR REPLACE FUNCTION func2(mode integer)
RETURNS integer AS
$BODY$
DECLARE
_result integer;
BEGIN
_result = 2;
IF mode=1 THEN
_result = func1();
END IF;
--more stuff .....
RETURN _result;
END
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
Option 2:
CREATE OR REPLACE FUNCTION func2(mode integer)
RETURNS integer AS
$BODY$
BEGIN
IF mode=1 THEN
RETURN func1();
END IF;
--more stuff .....
RETURN 2;
END
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;

PostgreSQL 9.3: isnumeric() in a condition

I need to check whether the given text is numeric or not from the
function.
Creating function for isnumeric():
CREATE OR REPLACE FUNCTION isnumeric(text) RETURNS BOOLEAN AS $$
DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
Function from which I am calling the isnumeric() function:
create or replace function tm(var text)
returns varchar as
$$
begin
if (select isnumeric(var))=t::BOOLEAN then
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
end;
$$
language plpgsql;
Calling functon:
select tm('1');
Getting an error:
Here is the error details:
ERROR: column "t" does not exist
LINE 1: SELECT (select isnumeric(var))=t::BOOLEAN
You don't need a select (and it's actually wrong, as the error indicates) - just call isnumeric directly.
Also, by the way, your function is missing a return statement.
To sum it all up:
create or replace function tm(var text)
returns varchar as
$$
begin
if (isnumeric(var)) then -- call isnumeric directly
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
return '0'; -- missing return value in the OP
end;
$$
language plpgsql;
this will help you to identify your field is numeric or not:
select * from Table where field_name ~ '^[0-9]*$'
for decimal values you can use^[0-9.]*$ instead ^[0-9]*$
select getDataType('2021'); == Number
select getDataType('2021-05-12 23:12:10'); == Date
select getDataType('2021-05-12'); == Date
select getDataType('2X'); == String
CREATE
OR REPLACE FUNCTION getDataType ( TEXT ) RETURNS TEXT AS $$ DECLARE
x VARCHAR;
BEGIN
x = $1 :: NUMERIC;
RETURN 'Number';
EXCEPTION
WHEN OTHERS THEN
BEGIN
x = $1 :: DATE;
RETURN 'Date';
EXCEPTION
WHEN OTHERS THEN
RETURN 'String';
END;
END;
$$ STRICT LANGUAGE plpgsql IMMUTABLE;

PL/pgSQL syntax error

I have a very simple PL/pgSQL script:
declare x varchar(100);
When I run it I get a message:
[WARNING ] declare x varchar(100)
ERROR: syntax error at or near "varchar"
LINE 1: declare x varchar(100)
^
I really don't understand what is wrong with this.
you can use procedural statements only inside function body in PostgreSQL.
CREATE OR REPLACE FUNCTION foo()
RETURNS int AS
$$ -- here start procedural part
DECLARE x int;
BEGIN
x := 10;
RETURN x;
END;
$$ -- here finish procedural part
LANGUAGE plpgsql; -- language specification
or in temporary function (anonymous block)
DO $$
DECLARE x int;
BEGIN
x := 10;
RAISE NOTICE '>>>%<<<', x;
END;
$$;
isn't possible to use procedural statements as SQL statements like T-SQL.
Use exemple
DO $$
Declare
test varchar;
begin
test := 'teste';
if (char_length(test) > 0) then
RAISE NOTICE '>>>%<<<', test;
end if;
end;
$$;
I have resolved this by the following piece of code:
do $$
declare TypeId int;
declare MasterId int;
begin
TypeId := null;
MasterId := null;
end;
$$;