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

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.

Related

How to modify column data-type while column is in used

I have problem while I use SELECT query. Unfortunettly, the ID is store as VARCHAR which is big mistake and right now I have problem in following function
FUNCTION GET_SUB_PROJECTS(p_currentUserId IN VARCHAR,p_projectId IN INT)
RETURN SYS_REFCURSOR IS
rc SYS_REFCURSOR;
-- getSubProject
BEGIN
OPEN rc FOR
SELECT
p.*,
a.number_ AS activityNumber,
a.description AS activityDescription
FROM
projects p
LEFT JOIN
project_users_schedule_dates pusd
ON
pusd.ProjectID = p.ProjectID AND pusd.UserID = p_currentUserId
LEFT JOIN
activities a
ON
a.id = p.activity
LEFT JOIN
responsible_persons rp
ON
rp.ProjectID = p.ProjectID AND rp.UserID = p_currentUserId
LEFT JOIN
users u
ON
u.UserID = p_currentUserId
WHERE
(u.User_roleID = 1 AND
p.CustomName LIKE CONCAT((SELECT CustomName FROM projects pr WHERE pr.ProjectID = p_projectId), '%') AND p.ProjectID <> p_projectId)
OR
((
(p.Responsible_person_id = p_currentUserId OR p.Delivery_contact = p_currentUserId OR rp.UserID = p_currentUserId OR (pusd.UserID = p_currentUserId AND SYSTIMESTAMP BETWEEN TO_DATE(pusd.StartDate,'YYYY-MM-DD') AND TO_DATE(pusd.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY AND
SYSTIMESTAMP BETWEEN TO_DATE(p.StartDate,'YYYY-MM-DD') AND TO_DATE(p.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY))
)
AND
p.CustomName LIKE CONCAT((SELECT CustomName FROM projects pr WHERE pr.ProjectID = p_projectId), '%') AND p.ProjectID <> p_projectId)
ORDER BY p.CustomName;
RETURN rc;
END GET_SUB_PROJECTS;
When I call function it needs to return data, but it doesn't. Somehow, here p.Responsible_person_id and p.Delivery_contact needs to be NUMBER but somehow it is VARCHAR
When I call function I use
SELECT PROJECT_PACKAGE.GET_SUB_PROJECTS('199',141) FROM DUAL
I found one solution to modify but It throw me error like
Error report -
ORA-01439: column to be modified must be empty to change datatype
01439. 00000 - "column to be modified must be empty to change datatype"
What to do in this situation ? What is the best method to solve this issue ?
You can change the data type of a column online using dbms_redefinition
create table t (
c1 varchar2(10)
primary key
);
create table t_new (
c1 number(10, 0)
primary key
);
insert into t values ( '1.0000' );
commit;
begin
dbms_redefinition.start_redef_table (
user, 't', 't_new',
col_mapping => 'to_number ( c1 ) c1',
options_flag => dbms_redefinition.cons_use_rowid
);
end;
/
exec dbms_redefinition.sync_interim_table ( user, 't', 't_new' );
exec dbms_redefinition.finish_redef_table ( user, 't', 't_new' );
desc t
Name Null? Type
C1 NOT NULL NUMBER(10)
select * from t;
C1
1
There are also options to copy constraints, triggers, indexes, etc. automatically in this process.

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.

Oracle decode null date variable

I have a query as part of a larger function and having trouble making DECODE work with null dates. This portion of my query is in the WHERE condition of the query:
NVL(datRunDate,SYSDATE)
BETWEEN NVL(EFFECTIVE_DATE,NVL(datRunDate,SYSDATE-1))
AND DECODE(STOP_DATE, NULL, NVL(datRunDate,SYSDATE + 1), STOP_DATE + (59/86400))
Where:
datRunDate DATE
EFFECTIVE_DATE DATE
STOP_DATE DATE
My issue is that the STOP_DATE is typically NULL and the DECODE doesn't work. Any ideas / help to work around this is appreciated.
EDIT
Adding some sample data as suggested:
datRunDate 2016-01-14 06:41:54
EFFECTIVE_DATE 2013-04-01 09:53:00
STOP_DATE NULL
EDIT2
Adding the entire query text here as the problem probably lies here. Note: I have replaced the variables manually. These variables are populated before this query with simple SELECT INTO statements.
datRunDate DATE;
SELECT COMP_DATE INTO datRunDate where IDL_SEQ = 2320;
SELECT EFFECTIVE_DATE, STOP_DATE from IDLS where IDL_SEQ = 2320;
DESC IDL_TABLE
DESC SCHEDULES COMP_DATE = datRunDate
...
SELECT I.IDL_SEQ
FROM IDLS I, IDL_CMPS IC
WHERE I.RECORD_TYPE = 'M'
AND IC.IDL_SEQ = I.IDL_SEQ
AND IC.CMP = '71-43-2'
AND I.METHOD = 'N0'
AND ((I.RUN_INSTRU = '') OR (I.RUN_INSTRU IS NULL))
AND ((I.PREP_METHOD = 'K9') OR (I.PREP_METHOD IS NULL))
AND ((I.MATRIX = 'SO') OR (I.MATRIX IS NULL))
AND ((I.COLUMN_ID = '') OR (I.COLUMN_ID IS NULL))
AND COALESCE(datRunDate, SYSDATE)
BETWEEN COALESCE(I.EFFECTIVE_DATE, datRunDate, SYSDATE - 1)
AND COALESCE(I.STOP_DATE + (59/86400), datRunDate, SYSDATE + 1)
AND ((I.SAMPLE_TYPE = 'SAMPLE') OR (SAMPLE_TYPE IS NULL))
AND ((I.CUST_SAMPLE_ID = 'SB-7') OR (CUST_SAMPLE_ID IS NULL))
AND ((I.LOCATION = '') OR (LOCATION IS NULL))
AND (
(OTHER_CRITERIA IS NOT NULL AND 404324 IS NOT NULL AND OTHER_CRITERIA = 'P|'||404324) OR
(OTHER_CRITERIA IS NOT NULL AND 28936 IS NOT NULL AND OTHER_CRITERIA = 'R|'||28936) OR
(OTHER_CRITERIA IS NOT NULL AND 'ECO' IS NOT NULL AND OTHER_CRITERIA = 'C|'||'ECO') OR
(OTHER_CRITERIA IS NULL));
Now when I run this I get: ORA-00932: inconsistent datatypes: expected CHAR got DATE
I would write this as:
COALESCE(datRunDate, SYSDATE) BETWEEN COALESCE(EFFECTIVE_DATE, datRunDate, SYSDATE - 1) AND
COALESCE(STOP_DATE + (59/86400), dateRunDate, SYSDATE + 1)
The ANSI standard function COALESCE() is simpler than using NVL() and DECODE() (which should be obsoleted anyway).

Oracle procedure 'with query' insert into table

I have created an Oracle SQL query in TOAD which works fine. I now need to put this in a procedure.
The query has to create two counts based on different criteria (I have used With Select) and insert these plus a date and location to a table.
The query that works is
with
Selected_animals as
( SELECT TO_CHAR(SYSDATE,'DD/MM/YYYY' ) as Report_Date,
loc.name location,
count(rran.id) as Count_exported
FROM rr_animals rran,
contact con,
locations loc,
names nam
WHERE con.connum = rran.connum
AND con.loc_id = loc.id
AND con.connum = nam.connum
AND nam.name_type = 'STAND'
AND nam.dob IS NOT NULL
AND rran.sex IS NOT NULL
AND rran.web_display = 'Y'
AND rran.web_description IS NOT NULL
AND rran.visit_end_date IS NULL
AND con.loc_id IS NOT NULL
AND con.datedl IS NULL
AND rran.hold_user IS NULL
AND rran.assess_status IS NULL
AND EXISTS (SELECT rrim.id
FROM rr_images rrim
WHERE rrim.image_type = 'KENNEL'
AND rrim.rran_id = rran.id
AND DBMS_LOB.GETLENGTH(rrim.image_object) >0
AND rrim.image_object IS NOT NULL)
group by loc.NAME ),
total_animals as
(select vbav.sitename as location,
count(vbav.rran_ID) as Count_available
from v_bx_all_animal_visits vbav
where visit_end_date is null
and concat != 'DELTD'
and concat != 'DSCD'
group by vbav.sitename)
select Total_animals.location,
Selected_animals.Report_date,
Selected_animals.count_exported,
Total_animals.count_available
from Selected_animals, total_animals
where total_animals.location = selected_animals.location(+)
I have looked at several ways that seem to write the procedure but nothing seems to work. Including which was added under the CREATE or REPLACE and before BEGIN:
( o_location out bx_webstats_export_available.LOCATION%TYPE,
o_date out bx_webstats_export_available.REPORT_DATE%TYPE,
o_exported out bx_webstats_export_available.COUNT_EXPORTED%TYPE,
o_available out bx_webstats_export_available.COUNT_AVAILABLE%TYPE )
Also added after the last where statement and before End:
INSERT INTO bx_webstats_export_available(location, report_date, count_export, count_available)
values (Total_animals.location,
Selected_animals.Report_date,
Selected_animals.count_exported,
Total_animals.count_available);
Can anyone help me get this query in a Procedure please?
This is the first time I have written a Procedure from scratch and I'm struggling with it.
Many thanks,
What is it you're trying to do? Insert the results of that select into a table? If so, the following ought to suffice:
create or replace procedure your_proc_name
as
begin
insert into bx_webstats_export_available(location, report_date, count_export, count_available)
with selected_animals as (select to_char(sysdate,'DD/MM/YYYY' ) as report_date,
loc.name location,
count(rran.id) as count_exported
from rr_animals rran,
contact con,
locations loc,
names nam
where con.connum = rran.connum
and con.loc_id = loc.id
and con.connum = nam.connum
and nam.name_type = 'STAND'
and nam.dob is not null
and rran.sex is not null
and rran.web_display = 'Y'
and rran.web_description is not null
and rran.visit_end_date is null
and con.loc_id is not null
and con.datedl is null
and rran.hold_user is null
and rran.assess_status is null
and exists (select rrim.id
from rr_images rrim
where rrim.image_type = 'KENNEL'
and rrim.rran_id = rran.id
and dbms_lob.getlength(rrim.image_object) >0
and rrim.image_object is not null)
group by loc.name),
total_animals as (select vbav.sitename as location,
count(vbav.rran_id) as count_available
from v_bx_all_animal_visits vbav
where visit_end_date is null
and concat != 'DELTD'
and concat != 'DSCD'
group by vbav.sitename)
select total_animals.location,
selected_animals.report_date,
selected_animals.count_exported,
total_animals.count_available
from selected_animals, total_animals
where total_animals.location = selected_animals.location(+);
end your_proc_name;
/
If not, then please explain a bit more about the requirements you're trying to satisfy.

ORA-01722: invalid number when creating materialized view

I am creating a view and the same view converted into materialized view in the same system. But doing the same thing in another system I got error ORA-01722: invalid number when creating the materialized view. Why?
create materialized view MV_EMP_VALI
refresh complete with rowid start with SYSDATE+1/24 AS
(select * from V_CHA1);
View:-
CREATE OR REPLACE VIEW V_CHA1 AS(SELECT EMPNO,
MONTHYEAR,
to_number(SUM(CPFEMO)) AS EMOLUMENTS,
to_number(SUM(CPEPF)) AS EMPPFSTATUARY,
to_number(SUM(AEMO)) AS AEMO,
to_number(SUM(APEPF)) AS APEPF,
MAX(recsts) AS recsts
FROM ((SELECT RECDATE,
(CASE WHEN (REPFEMOFLAG='N') THEN
round(NVL(trim(EMO), 0))
ELSE
round(NVL(REVISEMO, 0)) END ) as CPFEMO,
round(NVL(trim(EPF), 0)) AS CPEPF,
0 as AEMO,
0 as APEPF,
'' as recsts,
EMPNO
FROM EMP_VALI
WHERE EFLAG = 'Y' AND SFLAG = 'N' AND EMPNO IS NOT NULL and
RECDATE >'01-Apr-2011')
union all
(SELECT NDT.RECDATE AS RECDATE,
sum(round(NVL(trim(NDT.EMO), 0))) as CPFEMO,
sum(round(NVL(trim(NDT.EPF), 0))) as CPEPF,
0 as AEMO,
0 AS APEPF,
NDT.EMPNO
FROM EMP_VALI VAL, EMP_SUPP NDT
WHERE VAL.EMPNO = NDT.EMPNO AND VAL.EFLAG = NDT.EFLAG AND
VAL.EFLAG = 'Y' AND VAL.SFLAG = 'Y' AND
NDT.SLIFLAG='N' and
VAL.EMPNO is not null and
NDT.RECDATE = VAL.RECDATE
GROUP BY NDT.RECDATE, NDT.EMPNO) UNION ALL
(SELECT DT.RECPAIDDATE AS RECDATE,
0 as CPFEMO,
0 as CPEPF,
sum(round(NVL(trim(DT.EMO), 0))) as AEMO,
sum(round(NVL(trim(DT.EPF), 0))) AS APEPF,
max('') as recsts,
DT.EMPNO
FROM EMP_VALI VAL, EMP_SUPP DT
WHERE VAL.EMPNO = DT.EMPNO AND VAL.EFLAG = DT.EFLAG AND
VAL.EFLAG = 'Y' AND VAL.SFLAG = 'Y' AND
VAL.EMPNO IS NOT NULL and dt.RECDATE=val.RECDATE AND DT.SFLAG IS NOT NULL AND DT.SFLAG not in ('N','F')
GROUP BY DT.RECPAIDDATE, DT.EMPNO)UNION ALL
(SELECT DT.RECPAIDDATE AS RECDATE,
SUM((CASE
WHEN (DT.ECR4FLAG = 'C') then
round(NVL(trim(DT.EMO), 0))
else
0
end)) as CPFEMO,
sum((CASE
WHEN DT.ECR4FLAG = 'C' then
round(NVL(trim(DT.EPF), 0))
else
0
end)) as CPEPF,
sum((CASE
WHEN DT.ECR4FLAG = 'A' then
round(NVL(trim(DT.EMO), 0))
else
0
end)) as AEMO,
sum((CASE
WHEN DT.ECR4FLAG = 'A' then
round(NVL(trim(DT.EPF), 0))
else
0
end)) as APEPF,
max(EMPRECOVERYSTS) as recsts,
DT.EMPNO
FROM EMP_VALI VAL, EMP_SUPP DT
WHERE VAL.EMPNO = DT.EMPNO AND VAL.EFLAG = DT.EFLAG AND
VAL.EFLAG = 'Y' AND VAL.SFLAG = 'Y' AND
VAL.EMPRECSTS = 'DEP' AND VAL.EMPNO IS NOT NULL and
dt.RECDATE = val.RECDATE AND DT.SFLAG IS NOT NULL AND
DT.SFLAG in ('F')
GROUP BY DT.RECPAIDDATE, DT.EMPNO))
GROUP BY RECDATE, EMPNO)
/
It's hard to tell from the statement, but if I had to guess, I put my money on the expression:
RECDATE >'01-Apr-2011'
assuming the column RECDATE is actually of type DATE. Therefor Oracle tries to convert the character value '01-Apr-2011' to a DATE as well. As you did not specify an format mask for this, the default NLS settings are used. If they define a number for the month then the above value would fail conversion.
You should never rely on implicit data type conversion. Especially not with dates. Use an ANSI literal instead:
RECDATE > DATE '2011-04-01'
or use the to_date() function with a format mask:
RECDATE > to_date('01-Apr-2011', 'dd-mon-yyyy')
Note that this could still fail for certain settings of NLS_LANG. In French you would need to specify 'Avr' instead of 'Apr'. So unless you are absolutely certain you can control all NLS_XXX settings all the time I'd strongly suggest to use month numbers instead. If you are more comfortable using to_date() than ANSI literals, you can use:
RECDATE > to_date('01-04-2011', 'dd-mm-yyyy')
Edit
if it's not the date column you need to check any other column for implicit data conversions.
These expression:
sum(round(NVL(trim(DT.EMO), 0)))
round(NVL(trim(EMOLUMENTS), 0))
round(NVL(trim(DT.EMO), 0))
round(NVL(trim(DT.EPF), 0))
look suspicious. If the columns in there are real numbers, then trim() is invalid and useless. If those are not numbers they could cause that error depending on the content of the column.
This expression to_number(SUM(CPFEMO)) is also useless as sum() will already return a number there is no reason to call to_number on a number(). Although I doubt it could raise your error you should still avoid it as it does not make any sense.

Resources