Why this code is not going into IF block in PL/SQL? - oracle

I have below PL/SQL code and this is not going into IF block. Why is this not going into the IF Block?
Appreciate your responses.
DECLARE
p_datacenterid VARCHAR2(50) := '';
p_dcid VARCHAR2(50);
BEGIN
dbms_output.put_line('test');
-- Check if DataCenterId is null
IF nvl(p_datacenterid, '') = '' THEN
dbms_output.put_line('DataCenterID is empty');
SELECT datacenterid
INTO p_dcid
FROM pod_tab
WHERE url = 'dit3.ezlm.adp.com'
AND rownum = 1;
END IF;
END;
/

It looks like you are getting tripped up on comparing null values. An empty string is converted by Oracle into Null in the background. See here for details.
The IF statement ends up resolving to IF null = null which is never true.
Something like this would work
IF p_DataCenterID IS NOT NULL THEN
--assert the values are within a range
ELSE
--look up the value
END IF;

In PL/SQL and the Oracle database the empty string ('') is the same as NULL, and thus you must test for it as you would for NULL by using the IS NULL test instead of = NULL or = ''. Try running the following:
declare
p_DataCenterID varchar2(50) := ''; -- NOTE: '' is the same as NULL
p_dcID varchar2(50);
BEGIN
dbms_output.put_line( 'test');
-- Check if DataCenterId is null
IF p_DataCenterID IS NULL THEN
dbms_output.put_line('DataCenterID is empty');
SELECT DataCenterId
INTO p_dcID
FROM Pod_Tab
WHERE URL = 'dit3.ezlm.adp.com'
AND ROWNUM = 1;
END IF;
END;
/
This will print
test
DataCenterID is empty
Best of luck.

Related

Can i use REGEXP_LIKE as a condition with IF in a PL/SQL block and my string i will pass as parameter

if (NOT REGEXP_LIKE(l_hdr_high_amt_fare_tab(j).fare_basis,
L_HIGH_FARE_FLAG)) then
if l_total_fare > 13000 then
Begin
update tsapp_dwh_staging_tbl
set error_code = 'LA_QC_S10'
where sys_seq_no = p_sys_seq_no;
commit;
and my L_HIGH_FARE_FLAG is parameterized.
which is
+CHARTER(*)|+GRUPO(*)|+GROUP(*)
this is working if i hard-code this string in my code but when i pass string as parameter it wont work.
It worked with
SELECT '' || replace(a.value_text, ',', '|') || ''
FROM tmaac_app_parameters a
WHERE a.key_name = 'EMD_FLAG'
and a.module = 'IO'
and a.sub_module = 'EXTRACT'
and a.function = 'PARAMETER_PRCS';
If you just want to know whetherregexp_like will work in an if condition, then yes it will:
declare
function testit
( stringval varchar2 )
return varchar2
is
begin
if regexp_like(stringval,'^A') then
return 'Y';
else
return 'N';
end if;
end testit;
begin
dbms_output.put_line(testit('Abracadabra!'));
end;
/
Y
PL/SQL procedure successfully completed.
I'm not sure how l_high_fare_flag and tsapp_dwh_staging_tbl etc are related to the question.

Oracle initialization of collection elements with not null constraint

What is the initialization value for NOT NULL element in the collection (Table/Varray)? It seems like the NULL but it is NOT NULL. Tested in Oracle LIVE SQL (Oracle Database 19c Enterprise Edition - 19.2.0.0.0)
declare
type TArrNotNull IS table of number NOT NULL;
type TArrAllowNull IS table of number;
arrNotNull TArrNotNull := TArrNotNull();
arrAllowNull TArrAllowNull := TArrAllowNull();
begin
-- NOT NULL ARRAY ELEMENTS
DBMS_OUTPUT.PUT_LINE('======== table/Array of number NOT NULL example ==========');
arrNotNull.Extend;
IF arrNotNull(1) is null then
DBMS_OUTPUT.PUT_LINE('NULL !!!');
else
DBMS_OUTPUT.PUT_LINE('NOT NULL BUT WHAT ???->['||COALESCE(arrNotNull(1),100)||']');
DBMS_OUTPUT.PUT_LINE('NOT NULL BUT WHAT + 1 BECOMES NULL (LIKE REAL NULL)???->['||COALESCE(arrNotNull(1)+1,100)||']');
end if ;
DBMS_OUTPUT.PUT_LINE('======== table/Array of number example ==========');
-- NOT NULL ARRAY ELEMENTS
arrAllowNull.Extend;
IF arrAllowNull(1) is null then
DBMS_OUTPUT.PUT_LINE('OK IS NULL !!!');
else
DBMS_OUTPUT.PUT_LINE('NOT NULL !!!');
end if ;
end;
RESULTS:
Statement processed.
======== table/Array of number NOT NUMBER example ==========
NOT NULL BUT WHAT ???->[]
NOT NULL BUT WHAT + 1 BECOMES NULL (LIKE REAL NULL)???->[100]
======== table/Array of number example ==========
OK IS NULL !!!
UPD: Also the same if you assign the value to the NUMBER variable.
tst:=arrNotNull(1);
if tst is null then
DBMS_OUTPUT.PUT_LINE('N NULL !!!');
else
DBMS_OUTPUT.PUT_LINE('N NOT NULL !!!+++');
end if;
if (tst+1) is null then
DBMS_OUTPUT.PUT_LINE('N+1 NULL !!!+++');
else
DBMS_OUTPUT.PUT_LINE('N+1 NOT NULL !!!+++');
end if;
RESULT:
N NOT NULL !!!+++
N+1 NULL !!!+++
Very interesting. Didn't find a "value" for 18+, but in 12c you get a NULL.
I did shrink your code a little:
declare
type TArrNotNull IS table of varchar2(100) NOT NULL;
arrNotNull TArrNotNull := TArrNotNull(1, 2, 3);
begin
begin
arrNotNull(2) := to_number(NULL); -- will throw, because null is not allowed
dbms_output.put_line('arrNotNull(2) is null now');
exception
WHEN others THEN
dbms_output.put_line('arrNotNull(2) couldn''t be set to null');
end;
arrNotNull.Extend;
dbms_output.put_line('arrNotNull(4): >>>' || nvl(arrNotNull(4), 'NULL') || '<<<');
end;
Result in 12c:
arrNotNull(2) couldn't be set to null
arrNotNull(4): >>>NULL<<<
Result in 18c (same like yours):
arrNotNull(2) couldn't be set to null
arrNotNull(4): >>><<<
Also interesting is, that an Extend on a nullable Table of has NULL as default value:
declare
type TArrNotNull IS table of varchar2(100);
arrNotNull TArrNotNull := TArrNotNull(1, 2, 3);
begin
arrNotNull.Extend;
dbms_output.put_line('arrNotNull(4): >>>' || nvl(arrNotNull(4), 'NULL') || '<<<');
end;
Result on all versions:
arrNotNull(4): >>>NULL<<<

Error in PLSQL delete_document function

This is my PLSQL function to delete a document. SQLdeveloper complains. I know VARCHAR should be replaced with VARCHAR2, I am aware of that. There's something more than that. Package specification is absolutely fine.
FUNCTION delete_document (p_da_document_id IN da_documents.da_document_id%TYPE)
RETURN VARCHAR
IS
v_delete_status VARCHAR := 'N';
BEGIN
DELETE FROM da_document_key_values
WHERE da_document_id = p_da_document_id;
DELETE FROM da_document_tags
WHERE da_document_id = p_da_document_id;
DELETE FROM da_documents
WHERE da_document_id = p_da_document_id;
COMMIT;
SELECT COUNT(*) AS doc_count
FROM da_documents
WHERE da_document_id = p_da_document_id;
IF (doc_count = 0) THEN
v_delete_status := 'Y';
END IF;
RETURN v_delete_status;
END delete_document;
Just realised a procedure above has not been ended correctly. END; was missing. My mistake.

Oracle - How to tell between null and not null string?

In an anonymous block I have an input string that is empty/null and want to check that against a non-null string. Example:
DECLARE
v_notnull varchar2(50):='this string is never null';
v_input varchar2(50):='';
BEGIN
IF trim(v_input) != trim(v_notnull) THEN
dbms_output.put_line('the strings do NOT match');
ELSE
dbms_output.put_line('the strings DO match');
END IF;
END;
The issue here is that when I run this block, the output is always 'the strings DO match' even though I am inputting the empty string '' (aka null) into v_input which is not the same as the string 'this string is never null'. How can I make sure oracle covers the empty string case? When v_input is empty I want the output to be 'the strings do NOT match'.
The documentation has a section on null handling. An empty string is treated the same as null, and you cannot compare nulls (of any type) with equality - as the table in the documentation shows, the result of comparing anything with null is unknown - neither true nor false. You have to use is [not] null to compare anything with null.
In this case you could spell it out explicitly, by seeing is one variable is null and the other isn't, and vice versa, and only compare the actual values if that tells you neither are null:
DECLARE
v_notnull varchar2(30):='this string is never null';
v_input varchar2(30):='';
BEGIN
IF (trim(v_input) is null and trim(v_notnull) is not null)
or (trim(v_input) is not null and trim(v_notnull) is null)
or trim(v_input) != trim(v_notnull) THEN
dbms_output.put_line('the strings do NOT match');
ELSE
dbms_output.put_line('the strings DO match');
END IF;
END;
/
the strings do NOT match
PL/SQL procedure successfully completed.
I've added the missing varchar2 sizes; presumably you based this on a procedure that took arguments without running what you were posting stand-alone...
'' is NULL in oracle. So, any comparison with null will always result in false.
Demo:
SQL> DECLARE
2 v_notnull varchar2(1000):='this string is never null';
3 v_input varchar2(1000):='';
4 BEGIN
5 IF v_input is null THEN
6 dbms_output.put_line('v_input is null'); -- should print because v_input is actually null
7 END IF;
8
9 IF trim(v_input) = trim(v_notnull) THEN -- always false because of null
10 dbms_output.put_line('the strings do NOT match');
11 ELSE
12 dbms_output.put_line('the strings DO match'); -- so should print this
13 END IF;
14 END;
15 /
v_input is null -- verified
the strings DO match -- verified
PL/SQL procedure successfully completed.
SQL>
Often you only care whether the values match, in which case null values make no difference:
declare
v_notnull varchar2(50) := 'this string is never null';
v_input varchar2(50) := '';
begin
if trim(v_input) = trim(v_notnull) then
dbms_output.put_line('the strings DO match');
else
dbms_output.put_line('the strings do NOT match');
end if;
end;
In some cases you can simplify a comparison of nullable values using a coalesce() or nvl() expression:
if nvl(v_yesno,'N') <> 'Y' then ...
You might be able to use a dummy comparison value (although of course there is a risk that it will match an actual value, depending on the situation):
if nvl(somevalue, chr(0)) <> nvl(othervalue, chr(0)) then ...
By the way, you can distinguish between null and '' by copying the value to a char variable, as a '' will trigger its normally unhelpful blank-padding behaviour. I can't really think of a situation where this would be useful, but just for fun:
declare
v1 varchar2(1) := null;
v2 varchar2(1) := '';
c char(1);
begin
c := v1;
if v1 is null and c is not null then
dbms_output.put_line('v1 = ''''');
elsif c is null then
dbms_output.put_line('v1 is null');
end if;
c := v2;
if v2 is null and c is not null then
dbms_output.put_line('v2 = ''''');
elsif c is null then
dbms_output.put_line('v2 is null');
end if;
end;
Output:
v1 is null
v2 = ''

Calling an internal function inside a procedure PL/SQL

A bit green with PL/SQL functions but trying to add a function where if the current person does not have an alt_id to get the relative alt_id via the application. Many thanks in advance.
CREATE OR REPLACE PROCEDURE CLIENT.p_Verification(pin_Member_ID IN dbo.member.member_id%Type,
pin_Person_ID IN dbo.person.person_id%type,
pin_user_id IN NUMBER default null,
pioc_ref_cursor IN OUT dbo.pkg_benefit_q.ref_cursor) IS
lv_member_id dbo.person.alt_identifier%Type;
-- other variables
...
Procedure p_get_other_deductions(...
Begin
...
end;
new function here
FUNCTION f_get_alt_id
RETURN Varchar2
IS-- dbo.person.alt_identifier%Type IS
alt_id Varchar2(10); --dbo.person.alt_identifier%Type;
BEGIN
SELECT p.ALT_IDENTIFIER
into alt_id
FROM DBO.PERSON p , DBO.MEMBER m, DBO.APPLICATION a
where p.PERSON_ID = m.PERSON_ID
AND m.MEMBER_ID = a.MEMBER_ID
AND a.APPLICATION_ID= cn_EntAppId
;
RETURN alt_id;
END;
calling it here...
Select dbo.pkg_benefit_s.f_get_value_description('PREFIX',
p.prefix,
'Y',
'N') || case
when p.prefix is not null then
' '
else
Null
end || nvl2(p.first_name, initcap(p.first_name) || ' ', '') ||
nvl2(p.middle_name, initcap(p.middle_name) || ' ', '') ||
nvl2(p.last_name, initcap(p.last_name), '') || ' ' ||
dbo.pkg_benefit_s.f_get_value_description('SUFFIX',
p.suffix,
'Y',
'N'),
nvl2(p.alt_identifier,
f_get_alt_id, -- errors here
''),
nvl2(p.first_name, initcap(p.first_name), ''),
nvl2(p.last_name, initcap(p.last_name), '')
into lv_member_name,
lv_member_id,
lv_member_first_name,
lv_member_last_name
From dbo.person p
where p.person_id = ln_person_id;
... more code
END p_Verification;
/
It would be better practice in a number of ways to create a package that has your procedure and your function listed in the header and the body.
CREATE OR REPLACE PACKAGE CLIENT IS
PROCEDURE p_Verification(pin_Member_ID IN dbo.member.member_id%Type,
pin_Person_ID IN dbo.person.person_id%type,
pin_user_id IN NUMBER default null,
pioc_ref_cursor IN OUT dbo.pkg_benefit_q.ref_cursor);
Procedure p_get_other_deductions(...
FUNCTION f_get_alt_id(alt_id_in IN NUMBER:= NULL) RETURN Varchar2;
END CLIENT;
CREATE OR REPLACE PACKAGE BODY CLIENT IS
END CLIENT;
Notice how I have added a null parameter so if you need to redesign the function you can do so without invalidating any dependent objects.
I added the
alt_id varchar(10) in the declaration section
restored the select query above to simply return
dbo.pkg_benefit_s.f_get_value_description('SUFFIX',
p.suffix,
'Y',
'N'),
p.alt_identifier,
nvl2(p.first_name, initcap(p.first_name), ''),
nvl2(p.last_name, initcap(p.last_name), '')
into lv_member_name,
lv_member_id,
lv_member_first_name,
lv_member_last_name
... everything else is the same...until
I added another section to set the lv_member_id
BEGIN
Select p.alt_identifier
into alt_id
from dbo.person p
where P.PERSON_ID = pin_Person_id;
if alt_id is not null
then
lv_member_id := alt_id;
else
lv_member_id := f_get_alt_id;
end if;
END;
... rest of procedure and end; -- it now compiles

Resources