Oracle initialization of collection elements with not null constraint - oracle

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<<<

Related

Issue with variables and proc oracle

Im a beginner in oracle and i need help. I want to use variables in my proc but I dont know how to do it. I want to affect a string value to a variable depending to an other variable but when i lunch my proc nothing is happened. The code is not passing through the IF statement and I dont know why.
What I tried to do :
PROCEDURE contractual_control(p_id_depot IN depot.id_depot%TYPE) IS
-- Code_out proc
v_cod_out varchar(15) := null;
-- List of CODE KO_FCT
ko_fct_01 varchar(15) := 'KO_FCT_01';
ko_fct_02 varchar(15) := 'KO_FCT_02';
ko_fct_03 varchar(15) := 'KO_FCT_03';
ko_fct_04 varchar(15) := 'KO_FCT_04';
-- List of CODE KO_TEC
ko_tec_01 varchar(15) := 'KO_TEC_01';
ko_tec_02 varchar(15) := 'KO_TEC_02';
BEGIN
-----------------------------------------------------------------------------------------------------
-- CC1 - Objets interdits avec Presse Export - JIRA 968
-----------------------------------------------------------------------------------------------------
SELECT ko_fct_04 INTO v_cod_out FROM DEPOT_IMPORT
WHERE DEPOT_IMPORT.ID_ZONE IS NOT NULL
AND DEPOT_IMPORT.TYP_ELEMENT IN ('ENCART','INCARTO','INCPLUS','OPP');
IF v_cod_out is not null THEN
insert into babas_test values ('code retours = ' || v_cod_out);
ELSE
insert into babas_test values ('Pas de code retours');
END IF;
COMMIT;
END contractual_control;
Can you check your select statement ,probably it returns more than one row.
SELECT ko_fct_04 FROM DEPOT_IMPORT
WHERE DEPOT_IMPORT.ID_ZONE IS NOT NULL
AND DEPOT_IMPORT.TYP_ELEMENT IN ('ENCART','INCARTO','INCPLUS','OPP');
also you can add exception to your procedure to see the errors.
exception when others then
DBMS_OUTPUT.put_line ('ERROR :' || SQLERRM );

How to skip insert to an Oracle table in procedure where specified columns going to insert are null

I'm inserting lots of rows into a table and some of the columns are blank for some of the rows.
How can I skip insert if some important fields are blank?
for example there is a table 'people' and my important fields are name,cityName and age.
1 INSERT INTO people VALUES('customerid1','name', 'cityName', 50, 'anotherValue')
2 INSERT INTO people VALUES('customerid2','', '', '' , 'anotherValue')
3 INSERT INTO people VALUES('customerid3','name', 'cityName', 20, 'anotherValue')
4 INSERT INTO people VALUES('customerid4','name', 'cityName', 19, 'anotherValue')
here 2nd row name,cityName and age are blank.
if those three fields are blank then dont insert that row.this is just an example i have more fields to check so need to avoid 'if condition' to check blank or not.
another example
FUNCTION TEST_FUN (increment_i in VARCHAR2, increment_j IN VARCHAR2,mod_id IN VARCHAR2 )
RETURN numeric IS
j_val VARCHAR2(100);
i_val VARCHAR2(100);
BEGIN
i_val := increment_i;
j_val := increment_j;
IF mod_id != 'loop' THEN
j_val := i_val;
END IF;
INSERT
INTO TEST.testpartytable
(
reffer_id,
customer_id,
customer_joint,
fullname,
nature,
counter_bus,
country,
status
)
VALUES
(
REFFER_ID_AR,
CUSTOMER_ID_ARR(i_val),
CUSTOMER_JOINT,
LEGALNAME_KBC_ARR(i_val),
NATURERE_KBC_ARR(j_val),
COUNTERBUSACT_KBC_ARR(j_val),
COUNTRY_KBC_ARR(j_val),
STATUS
);
return i_val;
END TEST_FUN ;
skip insert if 'fullname,nature,counter_bus,country' fields are blank .Datas coming from colletion.
Any help is appreciated.
Thanks!
well you can check first if the values are null or not null:
declare CHECK_VAL varchar2(100);
BEGIN
select CUSTOMER_ID_ARR(i_val) into CHECK_VAL from dual;
if(i_val is not null) then
insert...
end if;
END;
You can alternavely make the column to not null, and raise exeception when you get error for a value not null.
You can apply a NOT NULL constraint to your important columns so that when any of them assigned with a NULL value an error will be raised, specifically ORA -1400 (cannot insert null) exception. You can then catch this exception in your program and just do nothing when this exception is raised.
Sample below,
CREATE TABLE TEST_TABLE
(col1 NUMBER NOT NULL, col2 NUMBER NOT NULL);
DECLARE
CANNOT_INSERT_NULL EXCEPTION;
PRAGMA EXCEPTION_INIT(cannot_insert_null, -1400);
num NUMBER;
BEGIN
FOR i IN 1..10 LOOP
num := 2;
IF i BETWEEN 3 AND 5 THEN
num := NULL; //since this is null, insert statement below will error and handled and won't be inserted
END IF;
BEGIN
INSERt INTO test_table
(col1,col2)
VALUES
(i, num);
EXCEPTION
WHEN CANNOT_INSERT_NULL THEN
NULL;
END;
END LOOP;
END;
/
SELECT *
FROM test_table;

Oracle Trigger with Multiple sequences filled on condition with relation to another sequence and column value

I have table to classifying Products as below
Category_ID VARCHAR2 (1024) NOT NULL, --PK
Category_Desc VARCHAR2 (1024) NOT NULL,
Class1_ID VARCHAR2 (1024),
Class1_Desc VARCHAR2 (1024),
Class2_ID VARCHAR2 (1024),
Class2_Desc VARCHAR2 (1024),
Class3_ID VARCHAR2 (1024),
Class3_Desc VARCHAR2 (1024),
Notes VARCHAR2 (1024),
column Category_ID filled by sequence Seq_Category_ID using trigger now
what I want to do is
filling column Class1_ID with value of column Category_ID concatenate with
it is sequence names Seq_Class1_ID
filling column Class2_ID with value of column Category_ID concatenate with Class1_ID concatenate with it is sequence names Seq_Class2_ID
and so on...
but I am getting error on that says
[Error] PLS-00103 (11: 4): PLS-00103: Encountered the symbol "{" when
expecting one of the following:
( begin case declare exit for goto if loop mod null pragma raise
return select update while with
mod continue current sql execute forall merge [Error]
PLS-00103 (13: 2): PLS-00103: Encountered the symbol "}" when
expecting one of the following:
( begin case declare else elsif end exit for goto if loop mod
null pragma raise return select update while with
finally
Is there any better way to manage the case I am talking about ?
CREATE OR REPLACE TRIGGER Trg_Category_ID_Seq
BEFORE INSERT
ON Product_Classification
FOR EACH ROW
WHEN (NEW.Category_ID IS NULL)
BEGIN
:NEW.Category_ID := Seq_Category_ID.NEXTVAL;
IF(NEW.Class1_Desc IS NOT NULL AND NEW.Category_ID IS NOT NULL AND NEW.Class1_ID IS NULL ) THEN
{
INSERT INTO Product_Classification (Class1_ID)VALUES(NEW.Category_ID||Seq_Class1_ID.NEXTVAL);
}
END;
When working with if conditions in block statements(or triggers) no need to use {} you close it with end if;
this way will fix your issue
CREATE OR REPLACE TRIGGER Trg_Category_ID_Seq
BEFORE INSERT
ON Product_Classification
FOR EACH ROW
when (NEW.Category_ID IS NULL)
BEGIN
:NEW.Category_ID := Seq_Category_ID.NEXTVAL;
IF(NEW.Class1_Desc IS NOT NULL AND NEW.Category_ID IS NOT NULL AND NEW.Class1_ID IS NULL ) THEN
INSERT INTO Product_Classification (Class1_ID)VALUES(NEW.Category_ID||Seq_Class1_ID.NEXTVAL);
end if;
END;
The syntax issues in your code:
the way you handle the IF THEN block, as said
you're missing some ':' while using NEW instead of :NEW.
How it should be:
CREATE OR REPLACE TRIGGER Trg_Category_ID_Seq
BEFORE INSERT
ON Product_Classification
FOR EACH ROW
WHEN (NEW.Category_ID IS NULL)
BEGIN
:NEW.Category_ID := Seq_Category_ID.NEXTVAL;
IF(:NEW.Class1_Desc IS NOT NULL AND :NEW.Category_ID IS NOT NULL AND :NEW.Class1_ID IS NULL ) THEN
INSERT INTO Product_Classification (Class1_ID)VALUES(:NEW.Category_ID||Seq_Class1_ID.NEXTVAL);
END IF;
END;

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 = ''

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

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.

Resources