What is wrong with my PLSQL Boolean Function? [duplicate] - oracle

I have a function in PL/SQL which checks if a particular emp_id exists or not which is:
CREATE OR REPLACE FUNCTION checkEmpNo(eno numeric)
RETURN boolean IS
emp_number number;
BEGIN
SELECT emp_id INTO emp_number
FROM emp;
IF eno=emp_number
THEN
return true;
ELSE
return false;
END IF;
END checkEmpNo;
The function compiles successfully, but when I try to run it as:
DECLARE
exist boolean;
BEGIN
exist=checkEmpNo(1);
dbms_output.put_line(exist);
END;
it returns the error:
ORA-06550: line 5, column 1:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 5, column 1:
PL/SQL: Statement ignored
3. BEGIN
4. exist:=checkEmpNo(1);
5. dbms_output.put_line(exist);
6. END;
EDIT:
I also tried this:
DECLARE
exist boolean:=true;
BEGIN
if(exist=checkEmpNo(1))
then
dbms_output.put_line('true');
else
dbms_output.put_line('false');
end if;
END;
And it returns the error: ORA-01422: exact fetch returns more than requested number of rows

dbms_output.put_line is not overloaded to accept a boolean argument. You can do something like
dbms_output.put_line( case when exist = true
then 'true'
else 'false'
end );
to convert the boolean into a string that you can then pass to dbms_output.
The ORA-01422 error is a completely separate issue. The function checkEmpNo includes the SELECT INTO statement
SELECT emp_id
INTO emp_number
FROM emp;
A SELECT INTO will generate an error if the query returns anything other than 1 row. In this case, if there are multiple rows in the emp table, you'll get an error. My guess is that you would want your function to do something like
CREATE OR REPLACE FUNCTION checkEmpNo(p_eno number)
RETURN boolean
IS
l_count number;
BEGIN
SELECT count(*)
INTO l_count
FROM emp
WHERE emp_id = p_eno;
IF( l_count = 0 )
THEN
RETURN false;
ELSE
RETURN true;
END IF;
END checkEmpNo;

Alternatively you can use the Oracle function diutil.bool_to_int to convert a boolean value to an integer: True -> 1, False -> 0.
dbms_output.put_line(diutil.bool_to_int(p_your_boolean));

Related

How to count rows from two columns?

I try to create the function login that takes customer number(pnr) and password from same table. Its fine to create function but test crashes with following eror:
ORA-00904: "P_PASSWD": invalid identifier
create or replace function logga_in(
p_pnr bankkund.pnr%type,
p_passwd bankkund.passwd%type
)
return number
as
v_resultat number(1);
begin
select count(pnr) into v_resultat
from bankkund
where p_pnr = pnr
and p_passwd = passwd;
return 1;
exception
when no_data_found then
return 0;
end;
There is one other problem with your code not suggested in the comments, A count function from a select into will not raise a NO_DATA_FOUND exception. You may use an IF condition on count or do something like this, which is preferable
CREATE OR REPLACE FUNCTION logga_in (
p_pnr bankkund.pnr%TYPE,
p_passwd bankkund.passwd%TYPE
) RETURN NUMBER AS
v_resultat NUMBER(1);
BEGIN
SELECT 1 --do not use count if you wish to handle no_data_found
INTO v_resultat FROM
bankkund WHERE pnr = p_pnr AND
passwd = p_passwd
AND ROWNUM = 1; --Add this
RETURN 1;
EXCEPTION
WHEN no_data_found THEN
RETURN 0;
END;
Now, as far as calling the procedure is concerned, there are various options available including using bind variable
VARIABLE p_pnr number --use the datatype of bankkund.pnr%TYPE
VARIABLE p_passwd VARCHAR2(10) --use the datatype of bankkund.passwd
SELECT logga_in(:p_pnr,:p_passwd) FROM dual;
Or substitution variable
SELECT logga_in('&p_pnr','&p_passwd') FROM dual;
Give inputs when prompted.
Or use PL/SQL block
DECLARE
v_res INT;
v_pnr bankkund.pnr%type := 12892; --or appropriate value
p_passwd bankkund.passwd%type := some_passwd';
BEGIN
v_res := logga_in();
If v_res = 1 THEN
do_something_u_want; --call or execute appropriate action.
END IF;
END;
/

PL/SQL: testing functions that return Boolean value

I am trying to test a PL/SQL function that returns a Boolean value. When I try to do this using the code below I get the error:
ORA-06550: Expression is of wrong type.
declare
v1 boolean;
begin
select plsql_package.plsql_function('arg1', 'arg2') into v1 from dual;
dbms_output.put_line('result = ' || v1);
end;
It won't work like that; DBMS_OUTPUT.PUT_LINE expects strings, not Boolean datatype, so you have to "convert" a Boolean datatype variable's value to a string - for example, using CASE (as I did). Have a look at this example:
SQL> create or replace function plsql_function return boolean as
2 begin
3 return false;
4 end;
5 /
Function created.
SQL> set serveroutput on
SQL> declare
2 v1 boolean;
3 begin
4 v1 := plsql_function;
5 dbms_output.put_line('result ' || case when v1 then 'true' else 'false' end);
6 end;
7 /
result false
PL/SQL procedure successfully completed.
SQL>
There are two errors in your code:
The BOOLEAN data type is a PL/SQL data type and does not exist in the SQL scope so
CREATE FUNCTION test_fn RETURN BOOLEAN IS BEGIN RETURN FALSE; END;
/
declare
v1 boolean;
begin
select test_fn() into v1 from dual;
end;
/
will fail with
ORA-06550: line 4, column 25:
PLS-00382: expression is of wrong type
because you are calling the function returning a PL/SQL only data type using SQL.
Instead, just assign the function result to the variable without using SQL:
declare
v1 boolean;
begin
v1 := test_fn();
end;
/
The both string concatenation operator || and DBMS_OUTPUT.PUT_LINE function do not accept a BOOLEAN argument.
BEGIN
DBMS_OUTPUT.PUT_LINE( FALSE );
END;
/
will fail with:
ORA-06550: line 2, column 3
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
and
DECLARE
v2 VARCHAR2(20);
BEGIN
v2 := 'result = ' || FALSE;
END;
/
will fail with:
ORA-06550: line 4, column 9
PLS-00306: wrong number or types of arguments in call to '||'
Instead, you need to convert the BOOLEAN data type to something it does accept like a VARCHAR2/CHAR:
DECLARE
v1 BOOLEAN := FALSE;
BEGIN
DBMS_OUTPUT.PUT_LINE( 'result = ' || CASE WHEN v1 THEN 'true' ELSE 'false' END );
END;
/

Function object is invalid

I was executing query in Oracle Application Express and it was fine. Until I run my application, it gives me error
Error in PLSQL code raised during plug-in processing.
ORA-06550: line 4, column 1: PLS-00905: object
PURCHASEORDER.ACLSTUDENT_CUSTOM_AUTH is invalid ORA-06550: line 4,
column 1: PL/SQL: Statement ignored
and this is my sql
create or replace FUNCTION aclstudent_custom_auth (
p_username IN VARCHAR2(50),
p_password IN VARCHAR2(20))
RETURN boolean IS
valid boolean;
BEGIN
FOR c1 IN (SELECT 1 FROM students
WHERE upper(student_userid) = upper(p_username)
AND upper(student_last_name) = upper(p_password))
LOOP
valid := TRUE;
RETURN valid;
END LOOP;
valid := FALSE;
RETURN valid;
END;
Declaration of input parameters of the function is without length.
CREATE OR REPLACE FUNCTION aclstudent_custom_auth (
p_username IN VARCHAR2,
p_password IN VARCHAR2)
RETURN boolean IS
valid boolean;
BEGIN
FOR c1 IN (SELECT 1 FROM students
WHERE upper(student_userid) = upper(p_username)
AND upper(student_last_name) = upper(p_password))
LOOP
valid := TRUE;
RETURN valid;
END LOOP;
valid := FALSE;
RETURN valid;
END;
This must work better.
As Massie says, don't specify length in your arguments. Also, as hinted by Lalit, your use of a return variable as well as two RETURN statements is superfluous. You should either just RETURN the required BOOLEAN value in one of two places or set the variable and have one RETURN at the end of the function. I'd go with the first approach as your code will be more concise.
Incidentally, I don't like using loops to check for the existence of one record, but that's by the by.
CREATE OR REPLACE FUNCTION aclstudent_custom_auth(p_username IN VARCHAR2,
p_password IN VARCHAR2)
RETURN BOOLEAN IS
BEGIN
FOR c1 IN (SELECT 1
FROM students
WHERE upper(student_userid) = upper(p_username)
AND upper(student_last_name) = upper(p_password)) LOOP
RETURN TRUE;
END LOOP;
RETURN FALSE;
END;
OR
CREATE OR REPLACE FUNCTION aclstudent_custom_auth(p_username IN VARCHAR2,
p_password IN VARCHAR2)
RETURN BOOLEAN IS
valid BOOLEAN;
BEGIN
FOR c1 IN (SELECT 1
FROM students
WHERE upper(student_userid) = upper(p_username)
AND upper(student_last_name) = upper(p_password)) LOOP
valid := TRUE;
END LOOP;
valid := FALSE;
RETURN valid;
END;

PL/SQL SQL*Plus Statement Ignored

I'm doing a trigger on my Oracle database, here's the code
CREATE OR REPLACE TRIGGER send_telegram_message
AFTER INSERT ON EVENT_LOG
FOR EACH ROW
DECLARE
GROUP_IDS VARCHAR(200);
BEGIN
IF :NEW.EVENT_ID AND :NEW.DESCRIPTION IS NOT NULL THEN
SELECT ID_GRUPO INTO GROUP_IDS
FROM V_EVENT_TELEGRAM
WHERE V_EVENT_TELEGRAM.EVENT_ID = :NEW.EVENT_ID;
TELEGRAM_BOT(GROUP_IDS,:NEW.DESCRIPTION);
END IF;
END;
When compile I'm getting the following error:
Error(4,3): PL/SQL: Statement ignored
Error(4,6): PLS-00382: expression is of wrong type
The problem seems to be with the type of group_ids variable, I've been trying to solve this PLS-00382 issue but I can't.
The "TELEGRAM_BOT()" line is a procedure call that invokes a Java published method:
create or replace PROCEDURE telegram_bot (group_ids VARCHAR2, message VARCHAR2)
AS LANGUAGE JAVA
NAME 'TelegramBot.subMain(String,String)';
The question has nothing to do with the triggers. You simply have a syntax error in the following line:
IF :NEW.EVENT_ID AND :NEW.DESCRIPTION IS NOT NULL THEN
if statement and logical operators expect a boolean expression. PL/SQL doesn't have implicit data type conversions to boolean values.
This means :NEW.EVENT_ID is not a valid boolean expression so it can't be used with and-operator and therefore the compilation fails with:
PLS-00382: expression is of wrong type
Essentially your problem can be narrowed down to the following example:
declare
v_foo number;
begin
-- compilation fails because a number (or any other non-boolean
-- data type) is not a boolean expression.
if v_foo
then
null;
end if;
end;
/
Working examples (compiles fine):
declare
v_foo number;
function to_boolean(p_x in number) return boolean is
begin
return p_x > 0;
end;
begin
-- a function returns a boolean value
if to_boolean(v_foo)
then
null;
end if;
-- a > operator returns a boolean value
if v_foo > 0
then
null;
end if;
-- is null operator returns a boolean value
if v_foo is null
then
null;
end if;
end;
/
Try this.
CREATE OR REPLACE TRIGGER send_telegram_message
AFTER INSERT ON EVENT_LOG
FOR EACH ROW
DECLARE
GROUP_IDS VARCHAR(200);
BEGIN
IF :NEW.EVENT_ID IS NOT NULL AND :NEW.DESCRIPTION IS NOT NULL THEN
SELECT ID_GRUPO INTO GROUP_IDS
FROM V_EVENT_TELEGRAM
WHERE V_EVENT_TELEGRAM.EVENT_ID = :NEW.EVENT_ID;
TELEGRAM_BOT(GROUP_IDS,:NEW.DESCRIPTION);
END IF;
END;

Use of boolean in PL/SQL

I have a function in PL/SQL which checks if a particular emp_id exists or not which is:
CREATE OR REPLACE FUNCTION checkEmpNo(eno numeric)
RETURN boolean IS
emp_number number;
BEGIN
SELECT emp_id INTO emp_number
FROM emp;
IF eno=emp_number
THEN
return true;
ELSE
return false;
END IF;
END checkEmpNo;
The function compiles successfully, but when I try to run it as:
DECLARE
exist boolean;
BEGIN
exist=checkEmpNo(1);
dbms_output.put_line(exist);
END;
it returns the error:
ORA-06550: line 5, column 1:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 5, column 1:
PL/SQL: Statement ignored
3. BEGIN
4. exist:=checkEmpNo(1);
5. dbms_output.put_line(exist);
6. END;
EDIT:
I also tried this:
DECLARE
exist boolean:=true;
BEGIN
if(exist=checkEmpNo(1))
then
dbms_output.put_line('true');
else
dbms_output.put_line('false');
end if;
END;
And it returns the error: ORA-01422: exact fetch returns more than requested number of rows
dbms_output.put_line is not overloaded to accept a boolean argument. You can do something like
dbms_output.put_line( case when exist = true
then 'true'
else 'false'
end );
to convert the boolean into a string that you can then pass to dbms_output.
The ORA-01422 error is a completely separate issue. The function checkEmpNo includes the SELECT INTO statement
SELECT emp_id
INTO emp_number
FROM emp;
A SELECT INTO will generate an error if the query returns anything other than 1 row. In this case, if there are multiple rows in the emp table, you'll get an error. My guess is that you would want your function to do something like
CREATE OR REPLACE FUNCTION checkEmpNo(p_eno number)
RETURN boolean
IS
l_count number;
BEGIN
SELECT count(*)
INTO l_count
FROM emp
WHERE emp_id = p_eno;
IF( l_count = 0 )
THEN
RETURN false;
ELSE
RETURN true;
END IF;
END checkEmpNo;
Alternatively you can use the Oracle function diutil.bool_to_int to convert a boolean value to an integer: True -> 1, False -> 0.
dbms_output.put_line(diutil.bool_to_int(p_your_boolean));

Resources