I need a SQL/Oracle function that compares two numbers
if number are even like( 22,10,4,12,6..) true
if are odd number like(3,7,13,5...) false.
CREATE OR REPLACE FUNCTION is_even(num_in NUMBER) RETURN BOOLEAN IS
BEGIN
IF MOD(num_in, 2) = 0 THEN
RETURN TRUE;
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END is_even;
/
CREATE OR REPLACE FUNCTION is_odd(num_in NUMBER) RETURN BOOLEAN IS
BEGIN
RETURN MOD(num_in, 2) = 1;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END is_odd;
One point not addressed in the other answer, which I have already mentioned in the comments and you don't seem to have paid attention to is that Boolean values can only be used in PL/SQL code, not in Oracle SQL.
This restricts you from calling your function through the most common method - to use it in a sql statement. If you try running this query with your function, it would fail.
select is_even(10) FROM DUAL;
ORA-06552: PL/SQL: Statement ignored
ORA-06553: PLS-382: expression is
of wrong type
You may call this function to set a Boolean PL/SQL variable, but it isn't very useful in a general scenario.
DECLARE
v_even_odd BOOLEAN := is_even(3);
Alternatively, you could return a number or a string ( "TRUE" / "FALSE" ).
CREATE OR REPLACE FUNCTION is_even (num_in NUMBER)
RETURN VARCHAR2
IS
BEGIN
IF MOD (num_in, 2) = 0
THEN
RETURN 'TRUE';
ELSE
RETURN 'FALSE';
END IF;
END is_even;
/
Which works fine while calling from sql.
select is_even(10) FROM DUAL;
IS_EVEN(10)
----------------
TRUE
I ready don't understand what is the difficulty here, as you yourself have provided the code for two functions above...
Anyway here you go:
CREATE OR REPLACE FUNCTION is_even(num_in NUMBER) RETURN BOOLEAN IS
BEGIN
IF MOD(num_in, 2) = 0 THEN
RETURN TRUE;
else
RETURN FALSE;
END IF;
END is_even;
/
Related
I am working on a package in PL/SQL.
This is my spec:
TYPE outrec IS RECORD(
tw_m_id NUMBER,
tw_m_dealer_id NUMBER,
tw_number NUMBER,
check_uid NUMBER);
TYPE outrecset IS TABLE OF outrec;
FUNCTION report
(
p_watermark IN NUMBER,
p_param IN NUMBER,
p_index IN NUMBER
) RETURN outrecset
PIPELINED;
This is my body:
FUNCTION func
(
p_watermark => p_watermark,
p_param => p_param,
p_index => p_index
)
RETURN outrecset
PIPELINED IS
temp outrec;
BEGIN
before_report(p_watermark => p_watermark,
p_param => p_param,
p_index => p_index);
FOR c_rec IN (SELECT tw_m_id,
tw_m_dealer_id,
tw_number,
package_name.somefunction(tw_number) AS check_uid
FROM table1
JOIN table2 rk ON id1 = rk.id2
WHERE 1 = 1
AND id1 = rk.id2
AND id1 = p_param)
LOOP
temp.tw_m_tw_rechnungskopf_id := c_rec.tw_m_tw_rechnungskopf_id;
temp.tw_m_haendler_id_rechnung := c_rec.tw_m_haendler_id_rechnung;
temp.check_uid := c_rec.check_uid;
PIPE ROW(temp);
END LOOP;
END;
I am trying to get value from package_name.somefunction(tw_number) AS check_uid. The problem is that somefunction returns BOOLEAN value.
When I set check_uid to BOOLEAN I get Error: PLS-00382: expression is of the wrong type because of course SQL doesn't support BOOLEAN. I tried :
CASE
WHEN package_name.somefunction(tw_number) THEN true
else false
END as check_uid
inside SELECT then I get Error: PL/SQL: ORA-00920: invalid relational operator.
Can someone tell me how to do this PL/SQL is not my strongest side :(
EDIT: I can't change somefunction to return for an example varchar2 it needs to stay the way it is
Write a simple wrapper function to convert the PL/SQL BOOLEAN to a NUMBER data type that is valid in SQL and expected by your record type and you can move the function call outside the SQL.
CREATE FUNCTION MAP_BOOLEAN( truthy IN BOOLEAN ) RETURN NUMBER DETERMINISTIC
IS
BEGIN
RETURN CASE truthy
WHEN TRUE THEN 1
WHEN FALSE THEN 0
ELSE NULL
END;
END map_boolean;
/
So your specification would be:
CREATE PACKAGE package_name IS
TYPE outrec IS RECORD(
tw_m_id NUMBER,
tw_m_dealer_id NUMBER,
tw_number NUMBER,
check_uid NUMBER
);
TYPE outrecset IS TABLE OF outrec;
-- Note: This may be in another package but is here for convenience.
FUNCTION somefunction(value IN NUMBER) RETURN BOOLEAN;
FUNCTION report
(
p_watermark IN NUMBER,
p_param IN NUMBER,
p_index IN NUMBER
) RETURN outrecset PIPELINED;
END;
/
and the corresponding body would be:
CREATE PACKAGE BODY package_name IS
FUNCTION somefunction(value IN NUMBER) RETURN BOOLEAN
IS
BEGIN
RETURN TRUE;
END;
PROCEDURE before_report(
p_watermark IN NUMBER,
p_param IN NUMBER,
p_index IN NUMBER
)
IS
BEGIN
NULL;
END;
FUNCTION report(
p_watermark IN NUMBER,
p_param IN NUMBER,
p_index IN NUMBER
) RETURN outrecset PIPELINED
IS
temp outrec;
BEGIN
before_report(
p_watermark => p_watermark,
p_param => p_param,
p_index => p_index
);
FOR c_rec IN (
SELECT tw_m_id,
tw_m_dealer_id,
tw_number
FROM table1
JOIN table2 rk ON id1 = rk.id2
WHERE id1 = p_param
)
LOOP
temp.tw_m_id := c_rec.tw_m_id;
temp.tw_m_dealer_id := c_rec.tw_m_dealer_id;
temp.check_uid := MAP_BOOLEAN(
PACKAGE_NAME.SOMEFUNCTION( c_rec.tw_number )
);
PIPE ROW(temp);
END LOOP;
END;
END;
/
(Note: you also need to update the cursor loop as the values you were selecting did not match the fields of the record.)
db<>fiddle here
Typically you would create an overloaded function in your package that returns 1/0 or Y/N. But since you have no access to the package you can use an inline function in your sql query to do this for you.
create or replace function func (parameter_i VARCHAR2) RETURN BOOLEAN
AS
BEGIN
return true;
END;
/
WITH
FUNCTION func_yn(parameter_i VARCHAR2)
RETURN NUMBER
IS
l_return_value BOOLEAN;
BEGIN
l_return_value :=func(parameter_i => parameter_i);
RETURN CASE l_return_value WHEN TRUE THEN 1 WHEN FALSE THEN 0 END;
END func_yn;
SELECT
func_yn('test')
FROM dual;
i'm trying to CALL a very simple PLSQL function and i can't guess what i'm doing wrong:
CREATE OR REPLACE PACKAGE BODY KYC_OWN.KYCK_TEMP IS
FUNCTION PrintHelloWorld RETURN VARCHAR2 IS
BEGIN
RETURN 'Hello World';
END printHelloWorld;
END KYCK_TEMP;
Then i call the function like this:
call KYC_OWN.KYCK_TEMP.PrintHelloWorld() INTO :x;
I guess i need to declare the x variable somewhere, but how?
Thanks in advance
You can try this:
CREATE OR REPLACE PACKAGE BODY KYC_OWN.KYCK_TEMP IS
FUNCTION PrintHelloWorld RETURN VARCHAR2 IS
BEGIN
RETURN ('Hello World');
END printHelloWorld;
END KYCK_TEMP;
or create a variable like below and return g_helloworld
create or replace package constants as
g_helloworld constant varchar2(11) := 'Hello World';
function get_helloworld return varchar2;
end constants;
/
create or replace package body constants as
function get_helloworld return varchar2
is
begin
return g_helloworld;
end get_helloworld;
end constants;
/
If you're in SQL*Plus, you could create a variable and then use that to hold the function return variable, e.g.:
VARIABLE x varchar2(30)
call KYC_OWN.KYCK_TEMP.PrintHelloWorld() INTO :x;
print x
or you could simply use an anonymous block, along with dbms_output to display the number:
set serveroutput on -- assuming you're in SQL*Plus
declare
v_val varchar2(30);
begin
v_val := KYC_OWN.KYCK_TEMP.PrintHelloWorld;
dbms_output.put_line('return val = '||v_val);
end;
I need help with functions in a package. The problem is that i got
two functions. The first function we can call it "function_a". The result from this function, how can I send it over in the function_b? What are the command to pass the result over to function_b?
The code is below:
CREATE OR REPLACE PACKAGE BODY test_PKG AS
FUNCTION F_a (F_h NUMBER, F_r NUMBER ) RETURN NUMBER
AS
V_PI NUMBER := 3.14;
V_BOTTEN NUMBER := F_r * F_r * V_PI;
V_VOLYM NUMBER;
BEGIN
V_VOLYM := F_h * V_BOTTEN;
RETURN V_VOLYM;
END F_a;
FUNCTION_B
.....
....
....
How can i get the result from v_volym in function_a to function_B?
Something like this:
CREATE OR REPLACE PACKAGE BODY test_PKG AS
FUNCTION F_a (F_h NUMBER, F_r NUMBER ) RETURN NUMBER
AS
V_PI NUMBER := 3.14;
V_BOTTEN NUMBER := F_r * F_r * V_PI;
V_VOLYM NUMBER;
BEGIN
V_VOLYM := F_h * V_BOTTEN;
RETURN V_VOLYM;
END F_a;
FUNCTION F_b RETURN NUMBER
AS
F_A_RESULT NUMBER;
BEGIN
F_A_RESULT := F_A(1,2);
RETURN F_A_RESULT;
END F_B;
PROCEDURE P_b (RESULT OUT NUMBER)
AS
BEGIN
RESULT := F_A(1,2);
END F_B;
....
Use Package variables. They will have scope across the package.
Lets say i have a package with three functions in it. then i create a stored procedure in PL/SQL. How can i call the package "test_pkg" from this procedure and represent the result from the functions?
here's how I'd do it.
CREATE OR REPLACE PACKAGE test_pack IS
FUNCTION foobar RETURN varchar2;
FUNCTION foo RETURN varchar2;
FUNCTION bar RETURN varchar2;
END test_pack;
CREATE OR REPLACE PACKAGE BODY test_pack IS
FUNCTION foobar RETURN varchar2 IS
BEGIN
return 'star';
END foobar;
FUNCTION foo RETURN varchar2 IS
BEGIN
return 'foo';
END foo;
FUNCTION bar RETURN varchar2 IS
BEGIN
return 'bar';
END bar;
END test_pack;
CREATE OR REPLACE PROCEDURE test_the_pack IS
BEGIN
DBMS_OUTPUT.PUT_LINE('foobar returns: ' || test_pack.foobar());
DBMS_OUTPUT.PUT_LINE('foo returns: ' || test_pack.foo());
DBMS_OUTPUT.PUT_LINE('bar returns: ' || test_pack.bar());
END test_the_pack;
How can I check if a function param is undefined?
procedure Test(aValue: TObject);
begin
if aValue <> nil then
ShowMessage('param filled') <-- also when Test() is executed!
else
ShowMessage('no param filled') <-- not called, only when Test(nil) is called
end;
However when this function is called in pure JS without a param,
then aValue = undefined, but the <> nil check is converted to == null!
For example, when you have a JS function with a callback:
type
TObjectProcedure = procedure(aValue: TObject);
procedure FetchUrlAsync(aUrl: string; aCallback: TObjectProcedure )
begin
asm
$().load(#aUrl, #aCallback);
end;
end;
You can call this function with:
FetchUrlAsync('ajax/test.html', Test);
It is now depended on jQuery if "Test" is called with a param or not.
In the next version, you'll be able to use Defined() special function, it will make a strict check against undefined (it will return true for a null value).
if Defined(aValue) then
...
In the current version you can define a function to check that
function IsDefined(aValue : TObject);
begin
asm
#result = (#aValue!==undefined);
end;
end;
In the current version (1.0) you can use the function varIsValidRef() to check if a value is undefined. The function is a part of w3system.pas so it's always there. It looks like this:
function varIsValidRef(const aRef:Variant):Boolean;
begin
asm
if (#aRef == null) return false;
if (#aRef == undefined) return false;
return true;
end;
end;
This checks for both null and undefined so you can use it against object references (type THandle is variant) as well.