PL SQL Function - How to call - sql

I have a function in PL/SQL as follows (being used in Oracle APEX):
create or replace FUNCTION User_Levels(result OUT VARCHAR2)
RETURN VARCHAR2 IS
v_user_types employee.user_type%TYPE;
BEGIN
SELECT user_type
INTO v_user_types
FROM Employee
WHERE upper(username) = v('APP_USER');
IF v_user_types = 1
THEN
result := 'TRUE';
ELSE
result := 'FALSE';
END IF;
END User_Levels;​
How can I call this just to see its current output in normal SQL i.e. does it evaluate to True or False at the time it is run.
Do I really need the OUT parameter called result?

From SQL*Plus:
var result varchar2(10);
var rc varchar2(10);
exec :rc := user_levels(:result);
print rc
print result
However, your function is invalid because you have no return clause. Since the only thing you can return is result, having that as both an out parameter and the return value is redundant. Which you keep depends on how you want to use it, but I'd suggest a function is more flexible and appropriate here.
create or replace FUNCTION User_Levels
RETURN VARCHAR2 IS
v_user_types employee.user_type%TYPE;
BEGIN
SELECT user_type
INTO v_user_types
FROM Employee
WHERE upper(username) = v('APP_USER');
IF v_user_types = 1 THEN
RETURN 'TRUE';
ELSE
RETURN 'FALSE';
END IF;
END User_Levels;​
/
... assuming v('APP_USER') does something sensible. You can then just do:
select user_levels from dual;

Should work. Typically, you would create a variable (like v_user_types) and return that (p_result). Also, you need to make sure that your v('APP_USER') is also uppercase.
Additionally, you can not run this from a SQL*PLUS or any command prompt as v('APP_USER') is application variable; therefore, you have to test this on an APEX page.
create or replace FUNCTION User_Levels(p_result OUT VARCHAR2)
RETURN VARCHAR2 IS
v_user_types employee.user_type%TYPE;
p_result VARCHAR2(10);
BEGIN
SELECT user_type
INTO v_user_types
FROM Employee
WHERE upper(username) = v('APP_USER');
IF (v_user_types = 1) THEN
p_result := 'TRUE';
ELSE
p_result := 'FALSE';
END IF;
RETURN p_result;
END User_Levels;​

Related

How to return null in OUT SYS_REFCURSOR

I have a procedure in the package which returns a SYS_REFCURSOR, i want to return null or empty based on a condition, not sure how can i do it.
PROCEDURE test( id_number IN VARCHAR2,
resultIN OUT SYS_REFCURSOR) AS
BEGIN
if true then
OPEN resultIN FOR
SELECT
fieldsValue
from TableName;
ELSE
Return empty resultIN ;
END IF;
END;
This is not working for me. How can I do the same.
You can use fake query as follows:
OPEN resultIN FOR
select * from dual where 1=2;
-- if you want one row also then use
OPEN resultIN FOR
select case when 1=2 then 1 end as dummy_row from dual;
It is important to use OPEN resultIN FOR otherwise application which is going to use it will directly throw closed cursor error. (Cursor is not opened.)
You can simply assign NULL to the refcursor like this:
PROCEDURE test( id_number IN VARCHAR2,
resultIN OUT SYS_REFCURSOR) AS
BEGIN
if false then
OPEN resultIN FOR
SELECT dummy
from dual;
ELSE
resultIN := null;
END IF;
END;

Basic question about PL/SQL SELECT statement, how to declare

I am trying to execute the function, but :
5/5 PLS-00103: begin function pragma procedure subtype type
current
cursor delete.
How can I repair it ?
create or replace function is_valid_value(resourceToCheck in varchar2,columnToCheck in varchar2,valueToCheck in varchar2)
return varchar2 is
v_value valid_values.resourceName%type;
declare
v_resource resourceToCheck;
v_name columnToCheck;
v_value valueToCheck ;
begin
begin
Select resourceName,columnName,validValue into v_resource,v_name,v_value
from valid_values
where
resourceName =resourceToCheck
AND columnName = columnToCheck
AND validvalue = valueToCheck
AND
upper(resourceName) = upper (valuetoCheck);
exception
when no_data_found then
return 0;
end;
return 1;
end is_valid_value ;
It seems you have several syntax errors in the routine:
-- function with 3 parameters
create or replace function is_valid_value(resourceToCheck in varchar2,
columnToCheck in varchar2,
valueToCheck in varchar2)
-- returns varchar2
return varchar2
is
-- uses 3 local variables; please, note their types
v_resource valid_values.resourceName%type;
v_name valid_values.columnName%type;
v_value valid_values.validValue%type;
begin
-- if we have a single record
select resourceName,
columnName,
validValue
into v_resource,
v_name,
v_value
from valid_values
where resourceName = resourceToCheck
and columnName = columnToCheck
and validvalue = valueToCheck
and upper(resourceName) = upper(valuetoCheck);
-- we return '1' (please, remember the declaration "return varchar2")
return '1';
exception
-- When we have no records
when no_data_found then
-- we return '0' (again, we return VarChar2)
return '0';
end is_valid_value;
You don't actually need the query to retrieve values just to indicate if there is a record or not. The following query seems to satisfy the requirement and be much simpler.
This way you avoid an EXCEPTION handler; neither return value is actually an exception so this seems more 'correct'.
I would also suggest using Y/N as the return if you want a VARCHAR2. Use 1/0 if you want to use a NUMBER. Mixing them could be confusing later for maintenance.
CREATE OR REPLACE FUNCTION is_valid_value(resourcetocheck IN VARCHAR2
, columntocheck IN VARCHAR2
, valuetocheck IN VARCHAR2)
RETURN VARCHAR2
IS
func_result VARCHAR2(1);
BEGIN
-- Indicate if it is a valid result
SELECT rec_exist
INTO func_result
FROM (SELECT '1' as rec_exist
FROM valid_values
WHERE resourcename = resourcetocheck
AND columnname = columntocheck
AND validvalue = valuetocheck
AND UPPER(resourcename) = UPPER(valuetocheck)
UNION ALL
SELECT '0' FROM dual)
WHERE rec_exist = 'Y' OR rownum = 1;
-- we return '1' (please, remember - VarChar2)
RETURN func_result;
END is_valid_value;

when I am trying to create a log_in function?Why I have error Error(3,10): PLS-00215: String length constraints must be in range (1 .. 32767)

I am trying to create a function to verify log_in by return 0(zero) if the login failed, or 1(one) if the login was successful by matching cust_id and Passwd as parametrars and I have two questions:
Why I get error bad bind p_cust_id?
How to return 0 when it fail?
.
create or replace function log_in
(
p_cust_id varchar2,
p_paswd varchar2
) return number
as p_all varchar2;
begin
select cust_id,passwd
into p_all
from customer
where cust_id=p_cust_id and passwd=p_paswd;
return 1;
end;
first of all, you are trying to select 2 column but into 1 variable. this can't be possible. check my fix below
select cust_id,passwd
into variable1, variable2
from customer
where cust_id=p_cust_id and passwd=p_paswd;
for your second requirement, you need to add below line before end.
EXCEPTION WHEN NO_DATA_FOUND THEN
return 0;
END;
EDIT
Your procedure can also be rewritten as
CREATE OR REPLACE FUNCTION LOG_IN
(
P_CUST_ID VARCHAR2,
P_PASWD VARCHAR2
) RETURN NUMBER
AS P_COUNT NUMBER;
BEGIN
SELECT COUNT(*)
INTO P_COUNT
FROM CUSTOMER
WHERE CUST_ID=P_CUST_ID AND PASSWD=P_PASWD;
IF (P_COUNT > 0)
RETURN 1;
END IF;
RETURN 0;
END;

SQL: Function select column into variable

I need to select two columns in two variables how can i do it, here the code
CREATE OR REPLACE FUNCTION checkUser(pUserName VARCHAR2, pCountry VARCHAR2)
RETURN NUMBER
IS
vUsername VARCHAR2(100);
vCountry VARCHAR2(100);
BEGIN
SELECT Person.Username INTO vUsername
FROM Person
WHERE Person.Username = pUserName;
EXCEPTION WHEN NO_DATA_FOUND THEN
vUsername := NULL;
SELECT Person.Country INTO vCountry
FROM Person
WHERE Person.Country = pCountry;
EXCEPTION WHEN NO_DATA_FOUND THEN
vCountry := NULL;
IF vUsername IS NULL OR vCountry IS NULL THEN
RETURN False;
ELSE
RETURN True;
END IF;
END checkUser;
Can i do that? I am new in SQL.
Based on what you are trying to do, the following code will give you the desired result. Note that RETURN NUMBER you are using is not right if you need to return strings 'True' or 'False' .
CREATE OR replace FUNCTION Checkuser(pusername VARCHAR2,
pcountry VARCHAR2)
RETURN VARCHAR2
IS
v_count NUMBER(10);
BEGIN
SELECT Count(1)
INTO v_count
FROM person p
WHERE p.username = pusername
AND p.country = pcountry;
IF v_count = 0 THEN
RETURN 'False';
ELSE
RETURN 'True';
END IF;
END checkuser;
Selecting more than a single column is not much more complicated than what you are doing at the moment :
SELECT p.Username,p.Country INTO vUsername, vCountry
FROM Person p
WHERE p.Username = pUserName AND p.Country = pCountry;
Just separate the columns with ',' after the SELECT and after the INTO.
Off topic, you need to make sure you don't have multiple records corresponding to your argument username and country otherwise you will have an error attempting to store a list of data in scalar variables.

Using Functions in triggers

I have created a function,which i think is right but im not sure how to call it in the trigger. I know the trigger is wrong but thats what i have tried
Function:
create or replace function log_in(pass in varchar2, user in varchar2)
return number
is
match_count number;
begin
select count(*)
into match_count
from Member
where username=user
and password=pass;
return match_count;
end;
Trigger:
create or replace TRIGGER PASSWORDCHECK
BEFORE INSERT OR UPDATE ON Login
FOR EACH ROW
DECLARE
usern VARCHAR2(12);
pass VARCHAR2(12);
result number;
BEGIN
usern := :new.username;
pass := :new.password;
/*Select LOG_IN(pass,usern)INTO result From MEMBER Where usern = Username;*/
result := LOG_IN(pass,usern);
If result = 1 THEN
dbms_output.put_line('Login Succesful');
ElsIF result = 0 THEN
dbms_output.put_line('Login Failed');
END IF;
END;
I'm assuming all login attempts fail?
USER is a keyword, which identifies the current schema:
SQL> select user from dual;
USER
------------------------------
REF
As it's unlikely any of your users have the same name as the schema your count is always returning 0.