What is the difference between "IS NOT NULL" and "NOT IN NULL"? Why these two Oracle queries return different results? - oracle

SELECT DUMMY FROM DUAL
WHERE DUMMY IS NOT NULL;
Result: Returns 'X';
SELECT DUMMY FROM DUAL
WHERE DUMMY NOT IN NULL;
Result: Returns nothing.

In Oracle binary expressions can evaluate to three states: TRUE, FALSE and NULL where NULL can be thought of as the same as a undefined or unknown value. Applying a binary operation to a NULL value will give a NULL output (and not, as you might expect, TRUE or FALSE):
Boolean Operation Result
----------------- ------
X = X TRUE
X = Y FALSE
X = NULL NULL
NULL = X NULL
NULL = NULL NULL
NULL IN ( NULL ) NULL
NOT TRUE FALSE
NOT FALSE TRUE
NOT NULL NULL
The query:
SELECT DUMMY FROM DUAL WHERE DUMMY NOT IN ( NULL )
is the equivalent of:
SELECT DUMMY FROM DUAL WHERE NOT( DUMMY = NULL )
And the WHERE clause evaluates NOT( DUMMY = NULL ) to NOT NULL which in turn evaluates to NULL. Since the WHERE filter evaluates to a non-TRUE value the row is excluded.
The IS NULL operation is specifically designed to test whether a value is NULL and will do what you intend where the equality = operator or IN operator will not.
So:
Boolean Operation Result
----------------- ------
NULL = NULL NULL
NULL IN ( NULL ) NULL
NULL IS NULL TRUE

DUMMY in DUAL is a varchar2, and you selected all DUMMY from DUAL that are not null (IS NOT NULL). DUAL has one row with DUMMY='X'.
Now you are saying that DUMMY is not IN a set of NULL, which makes no sense really and the select will return no result.
NULL is a special character, and is not zero. It represents the absence of real data (data which includes zeroes and empty spaces).

Related

Randomly getting "ORA-22814: attribute or element value is larger than specified in type" with a bulk collect into

I have code that is randomly getting "ORA-22814: attribute or element value is larger than specified in type" with a bulk collect into.
I suspect this is a data issue since it's random but PL/SQL is not my strong suit but I maintain an application that has a great deal of it in processing logic.
This is an Oracle 12c database.
Any help would be appreciated!
This is the block of code:
SELECT mxpv_activityupdate_O (
projectid,
task_id,
task_code,
pvtask_code,
task_name,
CASE
WHEN wbs_t0_id IS NOT NULL AND scgemergent_flag = 'Y'
THEN
wbs_t0_id
ELSE
wbs_pv_id
END,
act_start_date,
CASE
WHEN act_end_date IS NOT NULL AND (invalidactfinish_flag = 'Y')
THEN
NULL
ELSE
act_end_date
END,
NULL,
CASE WHEN invalidactuals_flag = 'Y' THEN NULL ELSE act_work_qty END,
MAX (oid),
scgemergent_flag,
invalidactuals_flag,
invalidactfinish_flag)
BULK COLLECT INTO u_all_tab
FROM (SELECT projectorganization,
projecttype,
projectid,
task_id,
task_code,
pvtask_code,
pvact_start_date,
task_name,
act_start_date,
act_end_date,
CASE
WHEN pvact_start_date IS NULL
AND act_start_date IS NULL
AND NVL (act_work_qty, 0) <> 0
THEN
'Y'
ELSE
'N'
END
invalidactuals_flag,
act_work_qty,
oid,
wbs_t0_id,
wbs_pv_id,
CASE
WHEN pvact_start_date IS NULL
AND (act_start_date IS NOT NULL --or nvl(act_work_qty,0)<>0
)
AND projectorganization = 'SCG'
AND projecttype = 'Daily'
AND pvtarget_start_date > v_t0_start_midnight + 7
THEN
'Y'
ELSE
'N'
END
scgemergent_flag,
CASE
WHEN act_end_date IS NOT NULL
AND NVL (act_start_date, pvact_start_date) IS NOT NULL
AND act_end_date <
NVL (act_start_date, pvact_start_date)
THEN
'Y'
ELSE
'N'
END
invalidactfinish_flag
FROM (SELECT oid,
projecttype,
wbs_t0.wbs_id wbs_t0_id,
--emergentwork,
projectorganization,
projectid,
task_id,
pvwbs_id wbs_pv_id,
activityid task_code,
task_code pvtask_code,
pvact_start_date,
pvtarget_start_date,
CASE
WHEN pvact_end_date IS NULL THEN activityname
ELSE NULL
END
task_name,
CASE
WHEN actualstart IS NOT NULL
AND ( pvact_start_date IS NULL
OR actualfinish IS NOT NULL)
THEN
actualstart
ELSE
NULL
END
act_start_date,
--actualstart act_start_date,
CASE
WHEN pvact_end_date IS NULL
AND ( pvact_start_date IS NOT NULL
OR actualstart IS NOT NULL)
THEN
actualfinish
ELSE
NULL
END
act_end_date,
NULL target_start_date,
CASE WHEN mxactualunits.proj_catg_short_name = 'Y' --and nvl(pvact_work_qty, 0) <> nvl(actuallaborhours,0)
THEN NVL (actuallaborhours, 0) ELSE NULL END
act_work_qty
FROM --1) activityid and proj id matches
(SELECT oid,
pv.task_id,
mx.proj_id,
mx.projectid,
pv.task_code,
pv.task_name,
pv.wbs_id pvwbs_id,
pv.act_start_date pvact_start_date,
pv.act_end_date pvact_end_date,
pv.target_start_date pvtarget_start_date,
mx.activityid,
mx.activityname,
mx.actualstart,
mx.actualfinish,
pv.act_work_qty pvact_work_qty,
mx.actuallaborhours,
mx.projectorganization,
mx.projecttype,
mx.process_start_ts --,
FROM mxpv_activity_tmp mx, mxpv_task_tmp pv
WHERE mx.task_id = pv.task_id
UNION
--3) PM Number/Job Plan number matches
SELECT oid,
jp.task_id,
jp.proj_id,
jp.proj_short_name,
jp.task_code,
jp.task_name,
jp.wbs_id,
jp.act_start_date pvtarget_start_date,
jp.act_end_date pvtarget_end_date,
jp.target_start_date pvtarget_start_date,
jp.activityid,
jp.activityname,
jp.actualstart,
jp.actualfinish,
jp.act_work_qty pvact_work_qty,
actuallaborhours,
projectorganization,
projecttype,
p_process_start_ts --,
FROM --3a) PM Number matches
(SELECT * FROM TABLE (pm_tab)
UNION
--3a) Job Plan Number matches
SELECT * FROM TABLE (jp_tab)) jp)
update_activity,
(SELECT projpcat.PROJ_ID, pcval.PROJ_CATG_SHORT_NAME
FROM privuser_PROJPCAT projpcat,
privuser_PCATTYPE pctype,
privuser_PCATVAL pcval
WHERE projpcat.PROJ_CATG_ID = pcval.PROJ_CATG_ID
AND pcval.PROJ_CATG_TYPE_ID =
pctype.PROJ_CATG_TYPE_ID
AND pctype.PROJ_CATG_TYPE = 'MX Actual Units')
mxactualunits,
(SELECT w.wbs_id, w.proj_id
FROM privuser_projwbs w, privuser_phase ph
WHERE w.phase_id = ph.phase_id
AND ph.phase_name = '0') wbs_t0
WHERE --update_activity.proj_id = actstrtoffset.proj_id (+)
update_activity.proj_id = wbs_t0.proj_id(+)
AND update_activity.proj_id = mxactualunits.proj_id(+)
AND update_activity.process_start_ts =
p_process_start_ts--and delete_ts is null
))
GROUP BY projectid,
task_id,
task_code,
pvtask_code,
task_name,
wbs_t0_id,
wbs_pv_id,
act_start_date,
act_end_date,
act_work_qty,
invalidactuals_flag,
invalidactfinish_flag,
scgemergent_flag,
pvact_start_date;
The type is defined as follows:
TYPE PV_APP_DATA.MXPV_ACTIVITYUPDATE_O AS OBJECT(
proj_short_name VARCHAR2 (100),
task_id NUMBER,
task_code VARCHAR2 (120 CHAR),
pvtask_code VARCHAR2 (120 CHAR),
task_name VARCHAR2 (120 CHAR),
wbs_id NUMBER,
act_start_date DATE,
act_end_date DATE,
target_start_date DATE,
act_work_qty NUMBER,
oid NUMBER,
scgemergent_flag VARCHAR2 (10),
invalidactuals_flag VARCHAR2 (100),
invalidactfinish_flag VARCHAR2 (100)
)
Please post if you need more information I wasn't sure what could be useful.
update 1 7/18/17
I modified the query with substr with no luck in fixing the problem:
select mxpv_activityupdate_O(
substr(projectid,0,99),
task_id,
substr(task_code,0,119),
substr(pvtask_code,0,119),
substr(task_name,0,119),
case when wbs_t0_id is not null and scgemergent_flag='Y' then wbs_t0_id
else wbs_pv_id end,
act_start_date,
case when act_end_date is not null and
(invalidactfinish_flag='Y'
)
then null else act_end_date end,
null,
case when invalidactuals_flag = 'Y' then null else act_work_qty end,
max(oid),
substr(scgemergent_flag,0,9),
substr(invalidactuals_flag,0,99),
substr(invalidactfinish_flag,0,99)
)
bulk collect into u_all_tab
from
(SELECT
projectorganization,
projecttype,
substr(projectid,0,99) as projectid,
task_id,
substr(task_code,0,119) as task_code,
substr(pvtask_code,0,119) as pvtask_code,
pvact_start_date,
substr(task_name,0,119) as task_name,
act_start_date,
act_end_date,
case when pvact_start_date is null and act_start_date is null
and nvl(act_work_qty, 0) <> 0 then 'Y' else 'N' end invalidactuals_flag,
act_work_qty,
oid,
wbs_t0_id,
wbs_pv_id,
case when pvact_start_date is null and
(act_start_date is not null --or nvl(act_work_qty,0)<>0
)
and projectorganization='SCG' and projecttype='Daily'
and pvtarget_start_date>v_t0_start_midnight+7
then 'Y' else 'N' end scgemergent_flag,
case when act_end_date is not null and nvl(act_start_date, pvact_start_date) is not null
and act_end_date<nvl(act_start_date, pvact_start_date) then 'Y' else 'N' end
invalidactfinish_flag
FROM
"if I want to force to correct length what's the best approach?"
You need to compare the length of the Tables' columns with the length of the Type's target attributes, and see which attributes are shorter than the columns you're trying to fit into them. Use the data dictionary.
For the Type Attributes use USER_TYPE_ATTRS (or ALL_TYPE_ATTRS if it's a different schema):
select attribute_name, attr_type_name, length, scale, precision
from user_type_attrs
where type_name = 'MXPV_ACTIVITY_UPDATE_O'
/
For the Table Columns it will be a similar query based on USER_TAB_COLS.
Once you have established the errant columns you will need to alter the type to enlarge the attributes. Alternatively apply SUBSTR() function to the columns in the query projection, to cut them down to size. Which is actually better depends on the circumstances of your application, although usually we would prefer the approach which doesn't lose data.

Optimize Insert statement

I have an insert block which inserts almost 5680969 rows and takes about 10 mins to execute. I tried to optimize using parallel hints and other things like summarizing queries. Can this block of query can be further optimized?? Any help will be much appreciated.
DECLARE
vblQueryName VARCHAR2(20);
BEGIN
vblQueryName:='060_745_085';
INSERT /*+ APPEND */ INTO TABLE_A
(
SOURCE,
SN,
CLMNUM,
CLAIMLINENUMBER,
CLMTYPE,
CLMTYPEDESC,
CLMCATEGORY,
MEMID,
ENRID,
RELFLAG,
MEMFIRSTNAME,
MEMLASTNAME,
GENDER,
DOB,
ADDR1,
ADDR2,
CITY,
STATE,
ZIP,
HOMEPHONE,
WORKPHONE,
LVLID1,
LVLDESC1,
LVLID2,
LVLDESC2,
LVLID3,
LVLDESC3,
LVLID4,
LVLDESC4,
LVLID5,
LVLDESC5,
LVLID6,
LVLDESC6,
LVLID7,
LVLDESC7,
LVLID8,
LVLDESC8,
LVLID9,
LVLDESC9,
LVLID10,
LVLDESC10,
FROMDATE,
TODATE,
SERVICEDATE,
RCVDATE,
PAIDDATE,
BILLTYPE,
POSCODE,
POSDESC,
SPECCODE,
SPECDESC,
DIAGCODE,
DIAGDESC,
FIRSTDIAGCODE,
FIRSTDIAGDESC,
SECONDDIAGCODE,
SECONDDIAGDESC,
THIRDDIAGCODE,
THIRDDIAGDESC,
FOURTHDIAGCODE,
FOURTHDIAGDESC,
FIFTHDIAGCODE,
FIFTHDIAGDESC,
SIXTHDIAGCODE,
SIXTHDIAGDESC,
SEVENTHDIAGCODE,
SEVENTHDIAGDESC,
EIGHTHDIAGCODE,
EIGHTHDIAGDESC,
NINTHDIAGCODE,
NINTHDIAGDESC,
TENTHDIAGCODE,
TENTHDIAGDESC,
PROCTYPE,
PROCCODE,
PROCDESC,
REVCODE,
DRGCODE,
MODIFIERCODE,
MODIFIERDESC,
CPT4_1,
CPT4_2,
CPT4_3,
HCPCS,
CPTII,
MODIFIERCODE2,
REVCODE1,
REVCODE2,
REVCODE4,
REVCODE3,
REVCODE5,
ICD9PROCCODE1,
ICD9PROCCODE2,
ICD9PROCCODE3,
ICD9PROCCODE4,
ICD9PROCCODE5,
ICD9PROCCODE6,
DRGTYPE,
DRGIDENTIFIER,
IPDAYS,
DISCHSTATUS,
TYPEOFBILL,
CLAIMSTATUS,
ADJCODE,
PROVID,
PROVNAME,
PROVIDERFIRSTNAME,
PROVIDERLASTNAME,
PROVNPI,
PROVZIPCODE,
SERVTYPECODE,
SERVTYPEDESC,
PROVTYPECODE,
PROVTYPEDESC,
SERVICECODE,
SPECROLLUPCODE,
SPECROLLUPDESC,
NWKID,
NWKNAME,
INNWK,
NETWORKTYPE,
SERVICEUNITS,
PAIDAMT,
BILLEDAMT,
ALLOWEDAMT,
PPOSAVINGAMT,
ENRPAIDAMT,
COINSAMT,
COPAYAMT,
DEDUCTAMT,
NOTALLOWEDAMT,
COBAMT,
PLANEXCLAMT,
LABTESTDATA,
SICCODE,
SICDESC,
SSN,
RCVMTH,
SRCFILENAME,
UDF1,
UDFC10,
UDFc19,
UDFc20,
ICDTYPE,
VHPAYORID
)
SELECT /*+PARALLEL(a,8) */
'SOURCE' AS SOURCE,
ROWNUM AS SN,
CASE UPPER(a.PROVIDER_NETWORK_PAR_INDICATOR) WHEN 'Y' THEN 'Y_' ELSE 'N_' END || a.CLAIM_NUMBER || a.CLAIM_LINE_NUMBER || ROWNUM AS CLMNUM,
a.CLAIM_LINE_NUMBER AS CLAIMLINENUMBER,
'MED' AS CLMTYPE,
'MEDICAL' AS CLMTYPEDESC ,
NULL AS CLMCATEGORY,
a.MEMID AS MEMID,
a.SUBSCRIBER_NUMBER AS ENRID,
NULL AS RELFLAG ,
UPPER(a.MEMBER_FIRST_NAME) AS MEMFIRSTNAME,
UPPER(a.MEMBER_LAST_NAME) AS MEMLASTNAME,
UPPER(a.MEMBER_GENDER) AS GENDER,
a.MEMBER_DATE_OF_BIRTH AS DOB,
a.MEMBER_ADDRESS_1 AS ADDR1,
a.MEMBER_ADDRESS_2 AS ADDR2,
a.MEMBER_CITY AS CITY,
a.MEMBER_STATE AS STATE,
a.MEMBER_ZIP AS ZIP,
a.MEMBER_PHONE AS HOMEPHONE,
NULL AS WORKPHONE,
'SOURCE' AS LVLID1,
'SOURCE' AS LVLDESC1,
NULL AS LVLID2,
NULL AS LVLDESC2,
NVL(lvl.VRSK_EMPLR_GRPID, REGEXP_REPLACE(a.subgroup_number,'[^a-zA-Z0-9]')) AS LVLID3,
NVL(lvl.EMPLOYER_GROUP_NM, REGEXP_REPLACE(a.subgroup_number,'[^a-zA-Z0-9]')) AS LVLDESC3,
NULL AS LVLID4,
NULL AS LVLDESC4,
NULL AS LVLID5,
NULL AS LVLDESC5,
NULL AS LVLID6,
NULL AS LVLDESC6,
NULL AS LVLID7,
NULL AS LVLDESC7,
NULL AS LVLID8,
NULL AS LVLDESC8,
NULL AS LVLID9,
NULL AS LVLDESC9,
NULL AS LVLID10,
NULL AS LVLDESC10,
a.SERVICE_START_DATE AS FROMDATE,
a.SERVICE_END_DATE AS TODATE,
a.SERVICE_START_DATE AS SERVICEDATE,
a.CLAIM_RECEIVED_DATE AS RCVDATE,
a.CLAIM_PROCESS_DATE AS PAIDDATE,
Decode(a.ENCOUNTER_TYPE_CODE, 'FCLTY', 'F', 'PROF', 'P', 'DENT', 'P') AS BILLTYPE,
a.PLACE_OF_SERVICE_CODE AS POSCODE,
NULL AS POSDESC,
e.ROLLUP_SPECCODE AS SPECCODE,
e.ROLLUP_SPECDESC AS SPECDESC,
COALESCE(a.PRIMARY_DIAGNOSIS_CODE,a.DIAGNOSIS_CODE_2,a.DIAGNOSIS_CODE_3,a.DIAGNOSIS_CODE_4,a.DIAGNOSIS_CODE_5) AS DIAGCODE,
NULL AS DIAGDESC,
a.PRIMARY_DIAGNOSIS_CODE AS FIRSTDIAGCODE,
NULL AS FIRSTDIAGDESC,
a.DIAGNOSIS_CODE_2 AS SECONDDIAGCODE,
NULL AS SECONDDIAGDESC,
a.DIAGNOSIS_CODE_3 AS THIRDDIAGCODE,
NULL AS THIRDDIAGDESC,
a.DIAGNOSIS_CODE_4 AS FOURTHDIAGCODE,
NULL AS FOURTHDIAGDESC,
a.DIAGNOSIS_CODE_5 AS FIFTHDIAGCODE,
NULL AS FIFTHDIAGDESC,
NULL AS SIXTHDIAGCODE,
NULL AS SIXTHDIAGDESC,
NULL AS SEVENTHDIAGCODE,
NULL AS SEVENTHDIAGDESC,
NULL AS EIGHTHDIAGCODE,
NULL AS EIGHTHDIAGDESC,
NULL AS NINTHDIAGCODE,
NULL AS NINTHDIAGDESC,
NULL AS TENTHDIAGCODE,
NULL AS TENTHDIAGDESC,
NULL AS PROCTYPE,
COALESCE(proc1.PROCCODE, proc2.PROCCODE, proc3.PROCCODE,a.PROCEDURE_CODE, NULLIF('I'||a.ICD_PROCEDURE_CODE_1,'I'), NULLIF('D'||a.AP_DRG,'D')) AS PROCCODE,
NULL AS PROCDESC,
CASE WHEN proc2.procTypeDesc='Rev Code' THEN proc2.PROCCODE END AS REVCODE,
proc3.PROCCODE AS DRGCODE,
NULL AS MODIFIERCODE,
NULL AS MODIFIERDESC,
CASE WHEN proc2.procTypeDesc='CPT4' THEN proc2.PROCCODE END AS CPT4_1,
NULL AS CPT4_2,
NULL AS CPT4_3,
CASE WHEN proc2.procTypeDesc='HCPCS' THEN proc2.PROCCODE END AS HCPCS,
NULL AS CPTII,
NULL AS MODIFIERCODE2,
CASE WHEN proc2.procTypeDesc='Rev Code' THEN proc2.PROCCODE END AS REVCODE1,
NULL AS REVCODE2,
NULL AS REVCODE4,
NULL AS REVCODE3,
NULL AS REVCODE5,
proc1.PROCCODE AS ICD9PROCCODE1,
REPLACE(a.ICD_PROCEDURE_CODE_2, '.') AS ICD9PROCCODE2,
REPLACE(a.ICD_PROCEDURE_CODE_3, '.') AS ICD9PROCCODE3,
NULL AS ICD9PROCCODE4,
NULL AS ICD9PROCCODE5,
NULL AS ICD9PROCCODE6,
NULL AS DRGTYPE,
NULL AS DRGIDENTIFIER,
NULL AS IPDAYS,
a.DISCHARGE_STATUS_CODE AS DISCHSTATUS,
NULL AS TYPEOFBILL,
NULL AS CLAIMSTATUS,
NULL AS ADJCODE,
coalesce(prov.rollupproviderid, a.provider_number) AS PROVID,
coalesce(prov.rollupprovidername,a.provider_name) AS PROVNAME,
NULL AS PROVIDERFIRSTNAME,
NULL AS PROVIDERLASTNAME,
NULL AS PROVNPI,
SubStr(a.PROVIDER_ZIP, 1, 5) AS PROVZIPCODE,
NULL AS SERVTYPECODE,
NULL AS SERVTYPEDESC,
NULL AS PROVTYPECODE,
NULL AS PROVTYPEDESC,
NULL AS SERVICECODE,
NULL AS SPECROLLUPCODE,
NULL AS SPECROLLUPDESC,
NVL(d.ROLLUPNWKID,a.PROVIDER_REGION_CODE) AS NWKID,
COALESCE(d.ROLLUPNWKNAME,a.PROVIDER_REGION_CODE) AS NWKNAME,
CASE UPPER(a.PROVIDER_NETWORK_PAR_INDICATOR) WHEN 'Y' THEN 'Y' ELSE 'N' END AS INNWK,
NULL AS NETWORKTYPE,
a.SERVICE_UNIT_COUNT AS SERVICEUNITS,
Nvl(a.PAID_AMOUNT,0) AS PAIDAMT,
Nvl(a.CHARGED_AMOUNT,0) AS BILLEDAMT,
Nvl(a.CHARGED_AMOUNT *0.54,0) AS ALLOWEDAMT,
NULL AS PPOSAVINGAMT,
NVL(a.COPAY_AMOUNT,0) + NVL(a.COINSURANCE_AMOUNT,0) + NVL(a.DEDUCTIBLE_AMOUNT,0) AS ENRPAIDAMT, -- corrected on /5/30/2013
Nvl(a.COINSURANCE_AMOUNT,0) AS COINSAMT,
Nvl(a.COPAY_AMOUNT,0) AS COPAYAMT,
Nvl(a.DEDUCTIBLE_AMOUNT,0) AS DEDUCTAMT,
Nvl(a.NOT_COVERED_AMOUNT,0) AS NOTALLOWEDAMT,
Nvl(a.COB_AMOUNT,0) AS COBAMT,
NULL AS PLANEXCLAMT,
NULL AS LABTESTDATA,
NULL AS SICCODE,
NULL AS SICDESC,
NULL AS SSN,
a.RECEIVEDMONTH AS RCVMTH,
a.SOURCEFILENAME AS SRCFILENAME,
'BCBSNC' AS UDF1 ,
a.SUBSCRIBER_NUMBER|| TO_CHAR(a.MEMBER_DATE_OF_BIRTH,'YYYYMMDD') AS UDFC10,--ICE176721
a.subgroup_number AS UDFc19,
a.benefit_package_id AS UDFc20,
CASE WHEN a.SERVICE_START_DATE>=to_date('20151001','YYYYMMDD') THEN 'ICD10' else 'ICD9' end as ICDTYPE,
payor.PAYORID AS VHPAYORID
FROM
HI0000001.HI_CLAIMS_SOURCE a
LEFT JOIN
HR_745_LOA_SOURCE lvl
ON
a.SUBGROUP_NUMBER = lvl.SUBGROUP_ID
LEFT JOIN
HR_745_NWK_CIGNA d
ON
a.PROVIDER_REGION_CODE = d.NWKID
AND
d.SOURCE = 'SOURCE'
LEFT JOIN
HR_745_SPEC_MERGED e
ON
a.PROVIDER_SPECIALTY_CODE = e.SRC_SPECCODE
AND
e.PAYER='BCBSNC'
LEFT JOIN
zzz_procs proc1
ON
'I'||REPLACE(a.ICD_PROCEDURE_CODE_1,'.') = proc1.proccode
LEFT JOIN
zzz_procs proc2
ON
CASE WHEN LENGTH(a.PROCEDURE_CODE)=4 AND SUBSTR(a.PROCEDURE_CODE,1,1)='0' THEN 'R'||SUBSTR(a.PROCEDURE_CODE,-3) ELSE a.PROCEDURE_CODE END = proc2.PROCCODE
LEFT JOIN
zzz_procs proc3
ON
'D'|| a.AP_DRG = proc3.proccode
LEFT JOIN
HR_GLOBAL_PAYORLIST payor
ON
payor.TABLENAME = 'HI_CLAIMS_BCBSNC'
LEFT JOIN
HR_745_PROVIDER prov
ON
'SOURCE' = prov.SOURCE
AND
UPPER(COALESCE(a.provider_number,'NULL')) = prov.provid
AND
UPPER(Nvl(a.provider_name, 'NULL')) = prov.provname
WHERE
a.ENCOUNTER_SERVICE_TYPE_CODE NOT IN ('06','02') AND a.ENCOUNTER_TYPE_CODE <>'CP'
AND
REGEXP_REPLACE(a.subgroup_number,'[^a-zA-Z0-9]') IS NOT NULL
AND
NVL(lvl.VRSK_EMPLR_GRPID, a.subgroup_number) NOT IN
(SELECT drp.lvl3id FROM hr_745_lvl3_drop drp WHERE source='BCBSNC')
AND
(NVL(lvl.VRSK_EMPLR_GRPID, a.subgroup_number)<>'539431' OR a.CLAIM_PROCESS_DATE<LAST_DAY(TO_DATE('2016-09','yyyy-mm')));
COMMIT;
DBMS_OUTPUT.PUT_LINE( 'Query Executed: ' || vblqueryName);
INSERT INTO VH_QUERYLOG(QueryName,CURTIME) VALUES(vblQueryName,SYSDATE);
EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
END;
/
Add this statement before the INSERT:
execute immediate 'alter session enable parallel dml';
Remove all the hints and only use this one hint at the top:
/*+ APPEND PARALLEL */
This allows the entire statement to run in parallel, not just certain parts of the SELECT. Unless you're using an old, unsupported version of Oracle, you normally want to avoid listing the objects in the parallel hint. Using the parallel hint without a number will hopefully pick a better degree of parallelism, depending on the way the system is setup. If that doesn't work out, then I'd recommend trying different numbers. (In short, a higher DOP is always faster, but there are diminishing returns and it can steal resources from other statements.)
After you've done that, take a look at the explain plan for the INSERT. Ensure it's using LOAD AS SELECT and not CONVENTIONAL INSERT - that's how you tell the statement is using a direct-path write. The APPEND hint is tricky and there are many things that may prevent it from working correctly.
Then run the code and generate a SQL Monitor report like this: select dbms_sqltune.report_sql_monitor(sql_id => 'the insert SQL_ID') from dual;. That report will tell you which operation in the query is slow, if any. The explain plan will probably generate a few dozen lines, and without the SQL Monitor report you'll have to guess which part is slow. Some of the join conditions look complicated, I wouldn't be surprised if you see a few operations where the estimated rows are 1 but the actual are much higher, leading to NESTED LOOPs instead of HASH JOINs.
Those are high-level hints for getting started with a parallel INSERT. You can easily spend hours on a statement like this.

Constraint check if row and other row not null on same time

I have a school 'project' to work on, which has some tables and one table needs to have a constraint which is not working out for me.
There are some tables like QUESTION, ANSWER and REACTION.
A reaction belongs with or a question or a answer but not both on the same time.
There by I have 2 rows:
question_id NUMBER,
answer_id NUMBER,
Both not null because the cant by null, but not on the same time.
I already made a constraint but isn't working..
/* CHECK if reaction belongs to an question or a answer NOT WORKING YET*/
CONSTRAINT CHECK_question_or_answer CHECK((answer_id != NULL AND question_id = NULL) OR (answer_id = NULL OR question_id != NULL))
Already tested the constraint and I can insert a value without a question_id or answer_id.
I hope it's a bit clear, if not, I am happy yo try explain myself better.
(still newby on SQL)
Thanks.
Your constraint:
CONSTRAINT CHECK_question_or_answer CHECK((answer_id != NULL AND profile_id = NULL) OR (answer_id = NULL OR profile_id != NULL))
Is always FALSE.
You need to use IS NULL or IS NOT NULL like:
CONSTRAINT CHECK_question_or_answer CHECK((answer_id IS NOT NULL AND profile_id IS NULL) OR (answer_id IS NULL OR profile_id IS NOT NULL))
This is because comparison operators != , = , > , <, combined with NULL produce NULL and are treated as false.
Demo:
SELECT 1
FROM dual
WHERE 1 IS NOT NULL;
SELECT 1
FROM dual
WHERE 1 != NULL;
From doc:
NULL values represent missing or unknown data. NULL values are used as
placeholders or as the default entry in columns to indicate that no
actual data is present. The NULL is untyped in SQL, meaning that it is
not an integer, a character, or any other specific data type.
Note that NULL is not the same as an empty data string or the
numerical value '0'. While NULL indicates the absence of a value, the
empty string and numerical zero both represent actual values.
While a NULL value can be assigned, it can not be equated with
anything, including itself.
Because NULL does not represent or equate to a data type, you cannot
test for NULL values with any comparison operators, such as =, <, or
<>.
The IS NULL and IS NOT NULL operators are used to test for NULL
values.
Do it the other way around. Put the id of the main table in the others like that
question table
--------------
id
text
...
answers table
-------------
id
question_id
text
...
reactions table
---------------
id
question_id
text
...
And question_id is never null. Then you can use a left join to get the results from both tables - one of them will have no results.
select *
from questions q
left join answers a on a.question_id = q.id
left join reactions r on r.question_id = q.id
While #lad2025s answer is good for two columns, if you wanted to extend the method to more than two it can get a bit cumbersome.
A flexible alternative is:
check ((case when answer_id is null then 0 else 1 end +
case when question_id is null then 0 else 1 end ) = 1)
It extends well to checking for a particular count of null (or non-null) values for an arbitrary number of columns.
For example, if you had column_1, column_2, column3, and column_4, and wanted at least 1 of them to be non-null, then:
check ((case when column_1 is null then 0 else 1 end +
case when column_2 is null then 0 else 1 end +
case when column_3 is null then 0 else 1 end +
case when column_4 is null then 0 else 1 end ) >= 1)

ORACLE SQL // IF ELSE?

I got a small problem in my SQL code :
LEFT JOIN
(SELECT *
FROM pilotage_usines_valeurs
WHERE c_indicateur IS NOT NULL) v
ON v.id_usine = d.id_usine
AND v.annee = 2015
AND V.MOIS = D.MOIS
AND V.C_INDICATEUR = pi1.c_indicateur
Sometime pi1.c_indicateur is null. How can i test it and write the line if pi1.c_indicateur is not null don't write it if pi1.c_indicateur is null ?
If I understand your intentions correctly I suggest you add the NOT NULL condition to the ON clause:
LEFT JOIN (SELECT *
FROM PILOTAGE_USINES_VALEURS
WHERE C_INDICATEUR IS NOT NULL) v
ON v.ID_USINE = d.ID_USINE
AND v.ANNEE = 2015
AND v.MOIS = D.MOIS
AND v.C_INDICATEUR = pi1.C_INDICATEUR
AND pi1.C_INDICATEUR IS NOT NULL
NVL is used to substitute null value by something else. Syntax is similar to
NVL (FIELD_TO_BE_TESTED_FOR_NULL, VALUE_IF_NULL);
Option 1:
Replace pi1.c_indicateur when null with some value so that V.C_INDICATEUR will never be equal to that value.
AND V.C_INDICATEUR = NVL(pi1.c_indicateur,'IMPOSSIBLE VALUE FOR V.C_INDICATEUR ');
Option 2:
Replace V.C_INDICATEUR with some value if null and replace pi1.c_indicateur with some other value, so that both will never match if NULL.
AND (V.C_INDICATEUR,'ABC') = NVL(pi1.c_indicateur,'DEF');

Oracle nvl in where clause showing strange results?

I have a web form that allows users to search on and edit records from an Oracle table based on parameters passed in to a proc. Here's my data:
CAE_SEC_ID SEC_CODE APPR_STATUS
1 ABC1 100
2 ABC2 100
3 ABC3 101
4 (null) 101
5 (null) 102
6 ABC4 103
And here's the where clause:
select foo
from bar
where CAE_SEC_ID = NVL(p_cae_sec_id,CAE_SEC_ID)
and Upper(SEC_CODE) like '%' || Upper(NVL(p_sec_code,SEC_CODE)) || '%'
and APPR_STATUS = NVL(p_appr_status, APPR_STATUS)
Using nvl on the parameters should return only the matched records if any of the parameters have values, and all records if none of the parameters have values. All pretty standard or so I thought. However when I do a search without any parameter values the query isn't returning records with a null SEC_CODE i.e. only records 1, 2, 3, and 6 are being returned. Shouldn't the where clause above include records with null SEC_CODE values?
The problem is that the SEC_CODE value in the table is NULL. That means that UPPER(sec_code) is NULL and your second predicate simplifies to
and NULL LIKE '%%'
Just like NULL is not equal to anything and not unequal to anything, it is not like anything. Most likely, you want something like
and (Upper(SEC_CODE) like '%' || Upper(NVL(p_sec_code,SEC_CODE)) || '%' or
(sec_code is null and p_sec_code is null))
That will return every row if P_SEC_CODE is NULL but still apply the filter if P_SEC_CODE is non-NULL.
No it shouldn't.
The SEC_CODE in the database is null, so the UPPER(SEC_CODE) is null and so it will fail on a LIKE match or pretty much any other comparison beyond IS NULL. Technically it is a UNKNOWN rather than a FALSE but is isn't enough to pass the test.
The expression NULL = NULL evaluates to NULL, which is not true and so these rows won't be returned. If I understand the requirement correctly, you only want to filter if a parameter is different from null, so I would rewrite the query like this to make the filter more explicit:
select foo from bar
where (p_cae_sec_id is null or CAE_SEC_ID = p_cae_sec_id)
and (p_sec_code is null or Upper(SEC_CODE) like '%' || Upper(p_sec_code) || '%')
and (p_appr_status is null or APPR_STATUS = p_appr_status)
Setting the p_sec_code parameter to null will now return all rows, ignoring the value in the SEC_CODE column.
We can also write the Jorn's query like
select foo from bar
where (CASE WHEN p_cae_sec_id is null THEN 'Y'
WHEN CAE_SEC_ID = p_cae_sec_id THEN 'Y'
ELSE 'N'
END)='Y'
and (CASE WHEN p_sec_code is null THEN 'Y'
WHEN Upper(SEC_CODE) like '%' || Upper(p_sec_code) || '%' THEN 'Y'
ELSE 'N'
END)='Y'
and (CASE WHEN p_appr_status is null THEN 'Y'
WHEN APPR_STATUS = p_appr_status THEN 'Y'
ELSE 'N'
END)='Y'
to make it concrete and increase the performance .

Resources