Return value from case statement in plpgsql - sql

How can I set a value (or just return a value directly) from a user defined function that uses a case statement?
create function is_bar(email varchar) returns boolean as
$$
declare returnValue boolean;
begin
select case when exists
(select * from (users join user_roles on users.userID = user_roles.userID)
where user_email=email and user_role='bar')
then (returnValue := TRUE);
else (returnValue := FALSE);
end;
return returnValue;
end;
$$ language plpgsql;
gives me:
ERROR: syntax error at or near ":="
LINE 8: then (returnValue := TRUE);

The reason of described issue is change of SQL (functional) CASE statement and PLpgSQL (procedural) CASE statement.
The SQL CASE (functional):
BEGIN
RETURN CASE WHEN EXISTS(..)
THEN true /* value */
ELSE false END; /* ended by END */
END;
The PLpgSQL (procedural) CASE:
BEGIN
CASE WHEN EXISTS(..)
THEN
RETURN true; /* statement */
ELSE
RETURN false;
END CASE; /* ended by END CASE */
END;
There are some other examples (same result):
a := CASE WHEN b < 10 THEN true ELSE false END;
a := b < 10;
CASE WHEN b < 10 THEN
a := true;
ELSE
a := false;
END CASE;

It would be much easier to return the result of the exists operator itself:
CREATE FUNCTION is_bar(email VARCHAR) RETURNS BOOLEAN AS
$$
BEGIN
RETURN EXISTS (SELECT *
FROM users
JOIN user_roles ON users.userID = user_roles.userID
WHERE user_email = email AND user_role='bar')
END;
$$ LANGUAGE plpgsql;

Related

getting an error 'function is_numeric(character varying) does not exist. ' in postgres

I have created a function in postgres with the below query but it says "function is_numeric(character varying) does not exist."
while executing the function.
I tried with "isnumeric" also, but no luck. same message.
Is there any alternate way to check whether the data value is numeric or not.
v_stmt := 'update '||user$get_name_table( id )||
' set err = err+1,err_val = err_val+1
where is_numeric('||u.column_name||')=0' ;
You can write your own function, for example:
CREATE OR REPLACE FUNCTION is_numeric(pval text)
RETURNS bool
LANGUAGE plpgsql
AS $function$
declare
vval float8;
begin
select pval::float8 into vval;
return true;
exception
when others then
return false;
end
$function$
;
select is_numeric('123') =>> true
select is_numeric('25.8654') =>> true
select is_numeric('H65D') =>> false

Stored Procedure in Snowflake: Use parameter in the where clause

I have following stored procedure in Snowflake:
create or replace procedure test_procedure(parameter varchar)
returns number
language sql
as
$$
begin
if ((SELECT MONTHLY_DELIVERED_AMOUNT FROM test.process.msv_month_amount where TARGET_KEY = parameter) = 0)
then
return null;
else
return (SELECT monthly_target_amount from test.process.msv_month_amount where TARGET_KEY = parameter);
end if;
end;
$$
;
call test_procedure('Key10');
When I try to call the test_procedure it give me following error:
SQL compilation error: error line 1 at position 98 invalid identifier 'parameter'
How do i fix this?
You should prefix the variable name with a colon.
create or replace procedure test_procedure(parameter varchar)
returns number
language sql
as
$$
begin
if ((SELECT MONTHLY_DELIVERED_AMOUNT FROM msv_month_amount where TARGET_KEY = :parameter) = 0)
then
return null;
else
return (SELECT monthly_target_amount from msv_month_amount where TARGET_KEY = :parameter);
end if;
end;
$$
;
call test_procedure('Key10');
Documentation links on the usage are provided below
https://docs.snowflake.com/en/developer-guide/snowflake-scripting/variables.html#using-a-variable-in-a-sql-statement-binding
https://docs.snowflake.com/en/sql-reference/stored-procedures-snowflake-scripting.html#calling-a-stored-procedure-without-using-the-returned-value
User Parameter with single colon (:)
create or replace procedure test_procedure(parameter varchar)
returns number
language sql
as
$$
begin
if ((SELECT MONTHLY_DELIVERED_AMOUNT FROM test.process.msv_month_amount where TARGET_KEY = :parameter) = 0)
then
return null;
else
return (SELECT monthly_target_amount from test.process.msv_month_amount where TARGET_KEY = :parameter);
end if;
end;
$$
;
call test_procedure('Key10');
The code could be simplified to single query and CASE expression:
SELECT CASE WHEN MONTHLY_DELIVERED_AMOUNT = 0 THEN NULL
ELSE monthly_target_amount
END
FROM msv_month_amount
WHERE TARGET_KEY = :parameter

PLSQL: using subquery in if-statement error PLS-00405

I'm getting error pls-00405 when I try to run this code:
BEGIN
IF :P10_KAART_CODE IN (SELECT KAART_CODE FROM CADEAUKAART) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
There are some similar questions about this but couldn't find a solution for this simple code. Is there another way of writing this without facing a error?
PL/SQL doesn't support embedded SQL in if statements. So you'll need to rewrite your code like this:
create or replace function validate_kaart_code
(P10_KAART_CODE in CADEAUKAART.KAART_CODE%type)
return boolean
is
rv boolean;
l_code CADEAUKAART.KAART_CODE%type;
BEGIN
begin
SELECT KAART_CODE into l_code
FROM CADEAUKAART
where KAART_CODE =:P10_KAART_CODE
and rownum = 1 -- only necessary if KAART_CODE is not unique
;
rv := TRUE;
exception
when no_data_found then
rv := FALSE;
end;
RETURN rv;
END;
I have attempted to reconstruct your whole functionality from the snippet you posted. If this isn't what you intended and you can't convert it to fit your needs please provide more details.
I'd move the condition to the query itself, and catch a NO_DATA_FOUND exception:
BEGIN
SELECT * FROM CADEAUKAART WHERE kaart_code = :P10_KAART_CODE;
RETURN TRUE;
EXCEPTION WHEN NO_DATA_FOUND THEN
RETURN FALSE;
END;
One more way:
CREATE OR REPLACE FUNCTION IS_KAART_CODE_VALID(pinKAART_CODE IN CADEAUKAART.KAART_CODE%TYPE)
RETURN BOOLEAN
IS
nCount NUMBER;
BEGIN
SELECT COUNT(*)
INTO nCount
FROM CADEAUKAART
WHERE KAART_CODE = pinKAART_CODE ;
RETURN CASE
WHEN nCount > 0 THEN
TRUE
ELSE
FALSE
END;
END IS_KAART_CODE_VALID;
You may try a cursor, alternatively :
DECLARE
v_flag boolean := FALSE;
BEGIN
FOR c IN ( SELECT KAART_CODE FROM CADEAUKAART )
LOOP
IF :P10_KAART_CODE = c.KAART_CODE THEN
v_flag := TRUE;
EXIT;
END IF;
EXIT WHEN NO_DATA_FOUND;
END LOOP;
RETURN v_flag;
END;
By your way using a select statement is not allowed, you might list all the members for the returning values of KAART_CODE such as
IF :P10_KAART_CODE IN ('aAA','BBb','ccC'..) THEN
but which is not preferable and nice to list all matching values .

use a validation function for an element in apex 5.0

I am trying to implement a validation on an application item in APEX 5.0. I am using a PL/SQL function returning a boolean
begin
if exists (select id_referencia
from items
where id_referencia = :P2_REFERENCIA)
then
return true;
else
return false;
end if;
end;
When I submit my page, I get the following error
ORA-06550: line 2, column 4: PLS-00204: function or pseudo-column
'EXISTS' may be used inside a SQL statement only ORA-06550: line 2,
column 1: PL/SQL: Statement ignored
if exists isn't valid PL/SQL syntax.
You could do a count(*) instead
declare
l_cnt integer;
begin
select count(*)
into l_cnt
from items
where id_referencia = :P2_REFERENCIA;
if( l_cnt >= 1 )
then
return true;
else
return false;
end if;
end;
If you really wanted to do an exists, you'd do something like this. I don't know why you'd want to do this assuming that id_referencia is the primary key of the table. But you could
declare
l_exists integer;
begin
begin
select 1
into l_exists
from dual
where exists( select 1
from items
where id_referencia = :P2_REFERENCIA );
exception
when no_data_found
then
l_exists := 0;
end;
if( l_exists = 1 )
then
return true;
else
return false;
end if;
end;
If you want to use EXISTS in a PL/SQL function returning BOOLEAN,try this
DECLARE
v_exist NUMBER;
BEGIN
SELECT 1
INTO v_exist
FROM DUAL WHERE EXISTS (select id_referencia
from items
where id_referencia = :P2_REFERENCIA)
IF v_exist IS NOT NULL
THEN
RETURN true;
ELSE
RETURN false;
END IF;
END;

Text equality (including null values) in Postgres plpgsql stored function

I have a stored function which is supposed to compare three text values for equality. Some of these text values may be null, and if they are, then the comparison should return a false value.
CREATE OR REPLACE FUNCTION "subject_check_if_subjectName_exists"(name1IN text, name2IN text, name3IN text, name4IN text)
returns boolean as
$$
declare
results boolean;
subjectList record;
begin
results = false;
for subjectList in select name1, name2, name3, name4 from subject loop
if (name1In = subjectList.name1) and (name2In = subjectList.name2) and (name3In = subjectList.name3) and (name4In = subjectList.name4)
then
results = true;
EXIT; -- exit out of loop
end if;
end loop;
return results;
end;
$$ language 'plpgsql';
Of both name4IN and subjectList.name4 are null, and all the other values are equal, the function doesn't return a true value - which it should. How can I compare these text values even if they are null (null = null should return true)?
I think you want to use is not distinct from:
For non-null inputs, IS DISTINCT FROM is the same as the <> operator. However, if both inputs are null it returns false, and if only one input is null it returns true. Similarly, IS NOT DISTINCT FROM is identical to = for non-null inputs, but it returns true when both inputs are null, and false when only one input is null.
Essentially, A is not distinct from B is like A = B but it treats NULLs as "equal" (i.e. it behaves like most SQL newcomers think = should). For example, consider a simple function like this:
create function f(text,text) returns text as $$
begin
if $1 is distinct from $2 then
return '!=';
end if;
return '==';
end $$
language plpgsql;
That will give you results like this:
=> select f(null, null) as "1"
f(null, '') as "2",
f('', '') as "3",
f('pancakes','pancakes') as "4",
f('pancakes', null) as "5",
f('pancakes', 'house') as "6";
1 | 2 | 3 | 4 | 5 | 6
----+----+----+----+----+----
== | != | == | == | != | !=
So something like this is what you're looking for:
if (name1In is not distinct from subjectList.name1) and ...
Essentially, this is what I want to do. I figured there must be a quicker way to compare values including null ones. This does what I want it to do:
-- Function to check subject names (name1,2,3 and 4) already exists
CREATE OR REPLACE FUNCTION "subject_check_if_subjectName_exists"(name1IN text, name2IN text, name3IN text, name4IN text)
returns boolean as
$$
declare
results boolean;
subjectList record;
begin
results = false;
for subjectList in select name1, name2, name3, name4 from subject loop
if ((subjectList.name4 is null) and (name4IN is null)) then
if ((subjectList.name3 is null) and (name3IN is null)) then
if ((subjectList.name2 is null) and (name2IN is null)) then
if (name1IN = subjectList.name1) then
results = true;
EXIT;
end if;
else
if ((name1IN = subjectList.name1) and (name2IN = subjectList.name2)) then
results = true;
EXIT;
end if;
end if;
else
if ((name1IN = subjectList.name1) and (name2IN = subjectList.name2) and (name3IN = subjectList.name3)) then
results = true;
EXIT;
end if;
end if;
else
if ((name1IN = subjectList.name1) and (name2IN = subjectList.name2) and (name3IN = subjectList.name3) and (name4IN = subjectList.name4)) then
results = true;
EXIT;
end if;
end if;
end loop;
return results;
end;
$$ language 'plpgsql';
Will try IS NOT DISTINCT FROM now.
Thank you for your help. Much appreciated!
Use coalesce:
if (coalesce(name1In, '') = coalesce(subjectList.name1, '') ....