Oracle stored procedure with function ORA-08103 - sql

I have a stored procedure that has a function call, and I get the below errors after about 10 mins of it running:
[Error] Execution (1: 1):
ORA-08103: object no longer exists
ORA-06512: at "CRYSTAL_REPORTS.FT_PAYCOM_ASOF", line 141
ORA-06512: at "CRYSTAL_REPORTS.PROC_DASHQS_PRODUCTION", line 26
ORA-06512: at line 2
However the function does exist and works as expected. Stripping down the query returns results, so I am concerned that complexity may be the cause. I appreciate any help, below is the procedure:
select
to_char(dt.dt,'YYYYMM') yearmonth,
ud.user_id,
CRYSTAL_REPORTS.FT_PAYCOM_ASOF(ud.user_eecode, dt.dt, 'DEPT') department,
CRYSTAL_REPORTS.FT_PAYCOM_ASOF(ud.user_eecode, dt.dt, 'PDEPT') par_department,
sum(case when clm.event_desc = 'NEW-OPEN' then 1 else 0 end) new_claim,
sum(case when clm.event_desc in ('INITIAL-CLOSE', 'RECLOSE', 'VOID') then 1 else 0 end) close_claim,
sum(case when clm.event_desc ='REOPEN' then 1 else 0 end) reopen_claim,
sum(case when clm.event_desc ='TRANSFER-IN' then 1 else 0 end) trans_in_claim,
sum(case when clm.event_desc ='TRANSFER-OUT' then 1 else 0 end) trans_out_claim,
sum(case when res.event_desc ='NEW-OPEN' then 1 else 0 end) new_res,
sum(case when res.event_desc in ('INITIAL-CLOSE','RECLOSE','VOID') then 1 else 0 end) close_res,
sum(case when res.event_desc ='REOPEN' then 1 else 0 end) reopen_res,
sum(case when res.event_desc ='TRANSFER-IN' then 1 else 0 end) trans_in_res,
sum(case when res.event_desc ='TRANSFER-OUT' then 1 else 0 end) trans_out_res,
sum(clm_wh.pending) pending_claims,
sum(res_wh.pending) pending_reserves
from
(select "DATE" dt from CRYSTAL_REPORTS.MV_CALENDAR_MONTHDATE) dt
cross join
crystal_reports.user_director ud
left join
CRYSTAL_REPORTS.MV_PROD_CLM_EVENT clm on clm.USER_ID = ud.USER_ID and to_char(clm.event_date,'YYYYMM') = to_char(dt.dt,'YYYYMM')
left join
CRYSTAL_REPORTS.MV_PROD_RES_EVENT res on res.USER_ID = ud.USER_ID and to_char(res.event_date,'YYYYMM')=to_char(dt.dt,'YYYYMM')
left join
crystal_reports.TBL_CLAIM_PROD_WH clm_wh on clm_wh.ADJUSTER=ud.user_id and clm_wh.type='MONTH' and to_char(dt.dt,'YYYYMM')= clm_wh.datadate
left join
crystal_reports.TBL_FEAT_PROD_WH res_wh on res_wh.ADJUSTER=ud.user_id and res_wh.type='MONTH' and to_char(dt.dt,'YYYYMM')= res_wh.datadate
where
to_char(dt.dt,'YYYYMMDD') = 20210901
and ud.user_id not like '%TEST%'
group by
to_char(dt.dt,'YYYYMM'), ud.user_id,
CRYSTAL_REPORTS.FT_PAYCOM_ASOF(ud.user_eecode, dt.dt, 'DEPT'),
CRYSTAL_REPORTS.FT_PAYCOM_ASOF(ud.user_eecode, dt.dt, 'PDEPT')
The function goes through several IF statements, and ends up using:
SELECT upper(case when uc_dept.detaildesc is null and orig_dept.detaildesc is null then upper(pext_dept.detaildesc) else upper(nvl(uc_dept.detaildesc,orig_dept.detaildesc)) end)
INTO xout_val
FROM crystal_reports.API_PAYCOM_USER_EXTENDED pext
left join crystal_reports.API_PAYCOM_USER_CHANGES uc on pext.EECODE = uc.EECODE and changedesc='PAF: Department Change' and (to_date(substr(changetime, 1,10), 'yyyy-mm-dd')) <= asof
left join crystal_reports.api_paycom_category pext_dept on pext_dept.detailcode=pext.DEPARTMENT_CODE
left join crystal_reports.api_paycom_category uc_dept on uc_dept.DETAILCODE=uc.new_value
left join (select eecode, orig_value,rn
from
(
select eecode,old_value orig_value, row_number() over (partition by eecode order by (to_date(substr(changetime, 1,10), 'yyyy-mm-dd')) asc) rn
from
crystal_reports.API_PAYCOM_USER_CHANGES orig_val
where changedesc='PAF: Department Change'
)
) orig_val on pext.eecode=orig_val.eecode and orig_val.rn=1
left join crystal_reports.api_paycom_category orig_dept on orig_dept.detailcode=orig_val.orig_value
where
acct=pext.eecode
order by (to_date(substr(changetime, 1,10), 'yyyy-mm-dd')) desc
FETCH NEXT 1 ROWS ONLY

It is very hard to remote diagnose such an error but in my experience the most likely cause of this error is another process/user that has removed the object since the operation has begun.
Alternatively there are also some Oracle bugs related to this error and you might want to check your alert log and eventually ask Oracle for help using MOS.

Related

SQL Server. dynamic query error while using aggregate function

I am little bit new to SQL. I am trying to run below shown dynamic query
SET #SQL ='
select Distinct count(*) TotalCount,
sum(case when ap.FormStatus = ''open'' then 1 else 0 end) AS Totalopenstatus,
sum(case when ap.FormStatus = ''Pending'' then 1 else 0 end) AS TotalPendingstatus,
sum(case when ap.FormStatus = ''Awaiting L1 Review'' then 1 else 0 end) AS TotalAssociates,
sum(case when ap.FormStatus = ''Awaiting L2 Review'' then 1 else 0 end) AS TotalL1reviews,
sum(case when ap.FormStatus = ''Awaiting Delivery Head'' then 1 else 0 end) AS TotalL2reviews
from [dbo].[Appraisals] ap
LEFT join [dbo].[FinalReviewClosures] fi ON ap.FinalReviewClosure_Id = fi.id
join [dbo].[employees] emp ON fi.Employee_Id = emp.id
where fi.FinancialYear ='+#FinancialYear +' AND ap.Quarter = '+#Quarter+' '
but I get this error:
Msg 245, Level 16, State 1, Procedure sp_GetReviewStatus, Line 51 [Batch Start Line 11]
Conversion failed when converting the nvarchar value
Code:
select Distinct count(*) TotalCount,
sum(case when ap.FormStatus = 'open' then 1 else 0 end) AS Totalopenstatus,
sum(case when ap.FormStatus = 'Pending' then 1 else 0 end) AS TotalPendingstatus,
sum(case when ap.FormStatus = 'Awaiting L1 Review' then 1 else 0 end) AS TotalAssociates,
sum(case when ap.FormStatus = 'Awaiting L2 Review' then 1 else 0 end) AS TotalL1reviews,
sum(case when ap.FormStatus = 'Awaiting Delivery Head' then 1 else 0 end) AS TotalL2reviews
from [dbo].[Appraisals] ap
LEFT join [dbo].[FinalReviewClosures] fi ON ap.FinalReviewClosure_Id = fi.id
join [dbo].[employees] emp ON fi.Employee_Id = emp.id
where fi.FinancialYear =2020-2021 AND ap.Quarter = Q3 AND emp.office = ' to data type int.
Please help me fix this problem.
The reason what you have is failing is as has been mentioned. You are injecting values instead of parametrising and these values are creating invalid syntax in your "dynamic" query. (Read on to see why I say "dynamic".)
fi.FinancialYear ='+#FinancialYear +' becomes fi.FinancialYear =2020-2021, which is effectively fi.FinancialYear = -1 (what year is -1?). This will cause an error if fi.FinancialYear isn't able to be converted implicitly to an int.
ap.Quarter = '+#Quarter becomes ap.Quarter = Q3 and unless you have a column called Q3 then you're going to get an invalid column error.
If you are using dynamic SQL then never inject unsanitised values; quote your object names using QUOTENAME and parametrise your parameters (which you can do with sys.sp_executesql).
What you have, however, has no need to be a "dynamic" query; there is nothing dynamic about it. Just use a non-dynamic parametrised query and the query will work fine:
SELECT --DISTINCT --Not needed, as the query will only return 1 row.
--Even if you did have a GROUP BY the DISTINCT isn't needed,
--as the GROUP BY will already put the data in DISTINCT sets.
COUNT(*) AS TotalCount,
SUM(CASE WHEN ap.FormStatus = 'open' THEN 1 ELSE 0 END) AS Totalopenstatus,
SUM(CASE WHEN ap.FormStatus = 'Pending' THEN 1 ELSE 0 END) AS TotalPendingstatus,
SUM(CASE WHEN ap.FormStatus = 'Awaiting L1 Review' THEN 1 ELSE 0 END) AS TotalAssociates,
SUM(CASE WHEN ap.FormStatus = 'Awaiting L2 Review' THEN 1 ELSE 0 END) AS TotalL1reviews,
SUM(CASE WHEN ap.FormStatus = 'Awaiting Delivery Head' THEN 1 ELSE 0 END) AS TotalL2reviews
FROM [dbo].[Appraisals] ap
LEFT JOIN [dbo].[FinalReviewClosures] fi ON ap.FinalReviewClosure_Id = fi.id
JOIN [dbo].[employees] emp ON fi.Employee_Id = emp.id
WHERE fi.FinancialYear = #FinancialYear --I assume fi.FinancialYear and #FinancialYear have the same data type?
AND ap.Quarter = #Quarter; --I assume ap.Quarter and #Quarter have the same data type?
Where clause should be
where fi.FinancialYear ='2020-2021' AND ap.Quarter = 'Q3' AND emp.office = ' to data type int.'
instead of
where fi.FinancialYear =2020-2021 AND ap.Quarter = Q3 AND emp.office = ' to data type int.
Please also let me know the data type of #financialYear and #Quarter

How to filter columns in addition to summing up in sql developer?

I wrote this code to get the number of risks with different status but I don't want the result in multiple rows, I just added the C_INSERTTIME field in order to filter the time later. how can i get the result in one row?
SELECT rsk.C_INSERTTIME inserttime,
SUM(CASE
WHEN rskst.c_code = 'HSE_RISK_STATUS_DRAFT' THEN 1
ELSE 0
END) AS drafted_risk,
SUM(CASE
WHEN rskst.c_code <> 'HSE_RISK_STATUS_DRAFT' THEN 1
ELSE 0
END) AS analyzed_risk,
SUM(CASE
WHEN rskdecsass.c_code = 'HSE_DECISION_ASSESSMENT_APPROVED' THEN 1
ELSE 0
END) AS approved_assessed_risks
FROM T_HSE_RISK rsk
LEFT JOIN t_hse_category_element rskst ON rskst.c_id = rsk.f_category_element_id_rsk_stts
LEFT JOIN t_hse_category_element rskdecsass ON rskdecsass.c_id = rsk.F_CTGRY_ELMNT_ID_DCSN_ASSSSMNT
WHERE rsk.C_INSERTTIME >= TIMESTAMP '2000-01-01 00:00:00'
GROUP BY rsk.C_INSERTTIME
You should remove the GROUP BY and use aggregation on C_inserttime as follows:
SELECT min(rsk.C_INSERTTIME) inserttime, -- or max
SUM(CASE
WHEN rskst.c_code = 'HSE_RISK_STATUS_DRAFT' THEN 1
ELSE 0
END) AS drafted_risk,
SUM(CASE
WHEN rskst.c_code <> 'HSE_RISK_STATUS_DRAFT' THEN 1
ELSE 0
END) AS analyzed_risk,
SUM(CASE
WHEN rskdecsass.c_code = 'HSE_DECISION_ASSESSMENT_APPROVED' THEN 1
ELSE 0
END) AS approved_assessed_risks
FROM T_HSE_RISK rsk
LEFT JOIN t_hse_category_element rskst ON rskst.c_id = rsk.f_category_element_id_rsk_stts
LEFT JOIN t_hse_category_element rskdecsass ON rskdecsass.c_id = rsk.F_CTGRY_ELMNT_ID_DCSN_ASSSSMNT
WHERE rsk.C_INSERTTIME >= TIMESTAMP '2000-01-01 00:00:00'
-- GROUP BY rsk.C_INSERTTIME -- removed this

SQL Year over Year Performance with Criteria

I am trying to return year over year results based on date criteria. There is additional information I would like to include in the query i.e. first date of activity and first date of activity with spot name like '%6%'. The current query I have is multiplying the correct amounts by 6 and I can't figure out how to solve. When I remove the first "where" clause I get the correct amounts. Any help would be appreciated.
Select
V.IGB_License,
DBA,
V.Sci_Games_Name,
convert(date,v2.Activity_date) as First6thMachineDate,
convert(date,V3.Activity_date) as GoLiveDate,
sum(case when (v.Activity_date between '1/23/2019' and DATEADD(YEAR,-2,getdate()-1)) then v.Funds_in else 0 end) as FundsIn2019,
sum(case when (v.Activity_date between '1/23/2020' and DATEADD(YEAR,-1,getdate()-1)) then v.Funds_in else 0 end) as FundsIn2020,
sum(case when (v.Activity_date between '1/23/2021' and getdate()) then v.Funds_in else 0 end) as FundsIn2021,
sum(case when (v.Activity_date between '1/23/2019' and DATEADD(YEAR,-2,getdate()-1)) then v.Net_funds else 0 end) as NetFunds2019,
sum(case when (v.Activity_date between '1/23/2020' and DATEADD(YEAR,-1,getdate()-1)) then v.Net_funds else 0 end) as NetFunds2020,
sum(case when (v.Activity_date between '1/23/2021' and getdate()) then v.Net_funds else 0 end) as NetFunds2021
From VGT_activity V
Left Join Locations on v.IGB_License = Locations.IGB_License
left join VGT_activity V2 on v.IGB_License = v2.IGB_License
Left join VGT_activity V3 on v.IGB_License = v3.IGB_License
Where v2.Activity_date = (
Select Min(V1.Activity_date)
From VGT_activity V1
Where v1.IGB_License = V2.IGB_License
and Spot_name like '%6%'
)
and v3.Activity_date = (
Select Min(V1.Activity_date)
From VGT_activity V1
Where v1.IGB_License = V3.IGB_License
)
group by V.IGB_License, dba, V.Sci_Games_Name, v2.Activity_date, v3.Activity_date
order by 4

Update a complex SQL query to add a new column with the sum of two columns

The below SQL query creates a table with n number of columns named in the next line.
...., curr_amount, tax_amount, ....
I am having a very tough time updating the below query to create a new column called total and position it exactly after tax_amount column and the total column should contain the values that are obtained after sum of curr_amount & tax_amount.
I have been working on this from more than one day but couldn't figure it out.
P.S. Still a noob here. Thanks alot for your time.
.
SELECT Isnull(t.total_month, 'Total') total_month,
t.tax_amount,
t.curr_amount,
t.usage_qty,
t.kh_qty,
t.bill_cnt
FROM (SELECT dbo.Sigmadf(bm.posted_date, 'YYYY-MM') total_month,
Sum(CASE
WHEN rr.usage_qty IS NULL THEN 0
ELSE Cast (rr.usage_qty AS NUMERIC(18, 2))
END) usage_qty,
Sum(CASE
WHEN bm.curr_amount IS NULL THEN 0
ELSE bm.curr_amount
END) curr_amount,
Sum(CASE
WHEN bm.adj_amount IS NULL THEN 0
ELSE bm.adj_amount
END) adj_amount,
Sum(CASE
WHEN bm.bal_fwd_amount IS NULL THEN 0
ELSE bm.bal_fwd_amount
END) bal_forward,
Sum(CASE
WHEN bm.tax_amount IS NULL THEN 0
ELSE bm.tax_amount
END) tax_amount,
Sum(CASE
WHEN bm.due_amount IS NULL THEN 0
ELSE bm.due_amount
END) due_amount,
Sum(CASE
WHEN bm.last_total_paid_amount IS NULL THEN 0
ELSE bm.last_total_paid_amount * -1
END) paid_amount,
Sum(CASE
WHEN bm.bill_print = 'Y' THEN 1
ELSE 0
END) pdf_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '0' THEN 1
ELSE 0
END) reg_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '1' THEN 1
ELSE 0
END) ftime_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '9999' THEN 1
ELSE 0
END) ltime_cnt,
Count(*) bill_cnt,
Sum(CASE
WHEN bill_status = '01' THEN 1
ELSE 0
END) canc_cnt,
Sum(CASE
WHEN bill_status = '01' THEN
CASE
WHEN rr.usage_qty IS NULL THEN 0
ELSE Cast (rr.usage_qty AS NUMERIC(18, 2))
END
ELSE 0
END) canc_usg,
Sum(CASE
WHEN vis.kh_qty IS NULL THEN 0
ELSE Cast(vis.kh_qty AS NUMERIC(18, 2))
END) kh_qty
FROM bill_master bm WITH (nolock)
INNER JOIN (SELECT bill_no,
Sum(CASE
WHEN vpb.recurr_charge_type IN ( 'T4',
'SLF' )
THEN
CASE
WHEN vpb.print_qty = 'Y'
AND vpb.usage_qty IS NOT NULL
THEN
Cast (vpb.usage_qty AS
NUMERIC(18, 2))
ELSE 0
END
ELSE 0
END) usage_qty
FROM v_print_bills_all vpb
GROUP BY bill_no) rr
ON rr.bill_no = bm.bill_no
LEFT OUTER JOIN vis_bill_master_cr vis WITH (nolock)
ON bm.bill_no = vis.bill_no
WHERE 1 = 1
AND dbo.Trunc(bm.posted_date) >= '20150101'
AND dbo.Trunc(bm.posted_date) <= '20151124'
AND bm.posted_date IS NOT NULL
AND bm.cust_id NOT IN (SELECT cc.code_type cust_id
FROM code_table cc WITH (nolock)
WHERE cc.code_tabname = 'RptExclCust'
AND cc.code_value = 'cust_id')
GROUP BY dbo.Sigmadf(bm.posted_date, 'YYYY-MM') WITH rollup)t
I must say that the explanation is not so clear.
From my understanding, you want the total of two columns.
So, wrap all your query between parenthesis, call it subQuery, and make the sum of the two columns on top:
SELECT subQuery.total_month as bill_date,
subQuery.curr_amount as amount,
subQuery.tax_amount tax,
subQuery.curr_amount + subQuery.tax_amount as [total],
...
FROM
(..your entire query here..) as subQuery

SQL - Dividing by Sum by Group

I am just learning SQL and have run into a problem creating a custom report. I am working with school attendance data. I want to create a report that gives membership days and number of days for each absence type.
I have successfully created a report for these separately.
Membership Days (calculated by counting days school was in session between the student's entry date and the current date. Membership days does not exist as a field on its own)
SELECT sum(case when cd.DATE_VALUE >= s.ENTRYDATE and cd.DATE_VALUE <= current_timestamp THEN cd.INSESSION ELSE 0 END), s.LASTFIRST
FROM CALENDAR_DAY cd,STUDENTS s
WHERE cd.SCHOOLID = 405
GROUP BY s.LASTFIRST
Count per absence type
SELECT s.STUDENT_NUMBER, s.LASTFIRST,SUM(CASE WHEN a.ATTENDANCE_CODEID = 2 THEN 1 ELSE 0 END),SUM(CASE WHEN a.ATTENDANCE_CODEID = 4 THEN 1 ELSE 0 END),SUM(CASE WHEN a.ATTENDANCE_CODEID = 3 THEN 1 ELSE 0 END),SUM(CASE WHEN a.ATTENDANCE_CODEID = 51 THEN 1 ELSE 0 END)
FROM ATTENDANCE a
INNER join STUDENTS s
ON a.STUDENTID = s.ID
WHERE a.att_date between '%param1%' and '%param2%'
GROUP BY s.STUDENT_NUMBER, s.LASTFIRST
The problem is that if I try to put these in the same report, the membership days are multiplied by the number of times the student appears in the attendance table due to joining student and attendance. My thought on a solution was to then divide this line
sum(case when cd.DATE_VALUE >= s.ENTRYDATE and cd.DATE_VALUE <= current_timestamp THEN cd.INSESSION ELSE 0 END)
by the number of times the student showed up in the attendance table to counteract the student information existing on every line. I can't figure out how to do that. I don't know much about these types of problems, so hopefully I've just gone off on the wrong track and there is an easy solution. Thanks.
Your problem is a common problem -- trying to summarize along two dimensions at the same time without using a subquery. You want to do this query with two aggregation subqueries. Something like this:
SELECT *
FROM (SELECT sum(case when cd.DATE_VALUE >= s.ENTRYDATE and cd.DATE_VALUE <= current_timestamp
THEN cd.INSESSION
ELSE 0
END), s. STUDENT_NUMBER
FROM CALENDAR_DAY cd CROSS JOIN
STUDENTS s
WHERE cd.SCHOOLID = 405
GROUP BY s.STUDENT_NUMBER
) sc JOIN
(SELECT s.STUDENT_NUMBER, s.LASTFIRST,
SUM(CASE WHEN a.ATTENDANCE_CODEID = 2 THEN 1 ELSE 0 END),
SUM(CASE WHEN a.ATTENDANCE_CODEID = 4 THEN 1 ELSE 0 END),
SUM(CASE WHEN a.ATTENDANCE_CODEID = 3 THEN 1 ELSE 0 END),
SUM(CASE WHEN a.ATTENDANCE_CODEID = 51 THEN 1 ELSE 0 END)
FROM ATTENDANCE a INNER join
STUDENTS s
ON a.STUDENTID = s.ID
WHERE a.att_date between '%param1%' and '%param2%'
GROUP BY s.STUDENT_NUMBER, s.LASTFIRST
) sa
on sc.STUDENT_NUMBER = sa.STUDENT_NUMBER;