ORA-01722: invalid number in Update query - oracle

I have following query and getting ORA-01722: invalid number
UPDATE SCHEDULE SET IS_ACTIVE = 0 WHERE REMINDER_ID IN ( SELECT replace('1,2', '''', '') as xtx FROM DUAL);
When I tried following way it executes , SELECT replace('1,2', '''', '') FROM DUAL;
I am getting (1,2) but this is not happening in the first query.

Got it and working - x_reminder_id = "'12,13'"
MERGE INTO SCHEDULE dst
USING (
SELECT REGEXP_SUBSTR(x_reminder_id, '\d+', 1, LEVEL) AS id
FROM DUAL
CONNECT BY LEVEL <= LEAST(
REGEXP_COUNT(x_reminder_id, '\d+')
)
) src
ON (src.id = dst.REMINDER_ID)
WHEN MATCHED THEN
UPDATE
SET IS_ACTIVE = 0;

Related

Adding filters in subquery from CTE quadruples run time

I am working on an existing query for SSRS report that focuses on aggregated financial aid data split out into 10 aggregations. User wants to be able to select students included in that aggregated data based on new vs. returning and 'selected for verification.' For the new/returning status, I added a CTE to return the earliest admit date for a student. 2 of the 10 data fields are created by a subquery. I have been trying for 3 days to get the subquery to use the CTE fields for a filter, but they won't work. Either they're ignored or I get a 'not a group by expression' error. If I put the join to the CTE within the subquery, the query time jumps from 45 second to 400 seconds. This shouldn't be that complicated! What am I missing? I have added some of the code... 3 of the chunks work - paid_something doesn't.
with stuStatus as
(select
person_uid, min(year_admitted) admit_year
from academic_study
where aid_year between :AidYearStartParameter and :AidYearEndParameter
group by person_uid)
--- above code added to get student information not originally in qry
select
finaid_applicant_status.aid_year
, count(1) as fafsa_cnt --works
, sum( --works
case
when (
package_complete_date is not null
and admit.status is not null
)
then 1
else 0
end
) as admit_and_package
, (select count(*) --does't work
from (
select distinct award_by_aid_year.person_uid
from
award_by_aid_year
where
award_by_aid_year.aid_year = finaid_applicant_status.aid_year
and award_by_aid_year.total_paid_amount > 0 )dta
where
(
(:StudentStatusParameter = 'N' and stuStatus.admit_year = finaid_applicant_status.aid_year)
OR
(:StudentStatusParameter = 'R' and stuStatus.admit_year <> finaid_applicant_status.aid_year)
OR :StudentStatusParameter = '%'
)
)
as paid_something
, sum( --works
case
when exists (
select
1
from
award_by_person abp
where
abp.person_uid = fafsa.person_uid
and abp.aid_year = fafsa.aid_year
and abp.award_paid_amount > 0
) and fafsa.requirement is not null
then 1
else 0
end
) as paid_something_fafsa
from
finaid_applicant_status
join finaid_tracking_requirement fafsa
on finaid_applicant_status.person_uid = fafsa.person_uid
and finaid_applicant_status.aid_year = fafsa.aid_year
and fafsa.requirement = 'FAFSA'
left join finaid_tracking_requirement admit
on finaid_applicant_status.person_uid = admit.person_uid
and finaid_applicant_status.aid_year = admit.aid_year
and admit.requirement = 'ADMIT'
and admit.status in ('M', 'P')
left outer join stuStatus
on finaid_applicant_status.person_uid = stuStatus.person_uid
where
finaid_applicant_status.aid_year between :AidYearStartParameter and :AidYearEndParameter
and (
(:VerifiedParameter = '%') OR
(:VerifiedParameter <> '%' AND finaid_applicant_status.verification_required_ind = :VerifiedParameter)
)
and
(
(:StudentStatusParameter = 'N' and (stuStatus.admit_year IS NULL OR stuStatus.admit_year = finaid_applicant_status.aid_year ))
OR
(:StudentStatusParameter = 'R' and stuStatus.admit_year <> finaid_applicant_status.aid_year)
OR :StudentStatusParameter = '%'
)
group by
finaid_applicant_status.aid_year
order by
finaid_applicant_status.aid_year
Not sure if this helps, but you have something like this:
select aid_year, count(1) c1,
(select count(1)
from (select distinct person_uid
from award_by_aid_year a
where a.aid_year = fas.aid_year))
from finaid_applicant_status fas
group by aid_year;
This query throws ORA-00904 FAS.AID_YEAR invalid identifier. It is because fas.aid_year is nested too deep in subquery.
If you are able to modify your subquery from select count(1) from (select distinct sth from ... where year = fas.year) to select count(distinct sth) from ... where year = fas.year then it has the chance to work.
select aid_year, count(1) c1,
(select count(distinct person_uid)
from award_by_aid_year a
where a.aid_year = fas.aid_year) c2
from finaid_applicant_status fas
group by aid_year
Here is simplified demo showing non-working and working queries. Of course your query is much more complicated, but this is something what you could check.
Also maybe you can use dbfiddle or sqlfiddle to set up some test case? Or show us sample (anonimized) data and required output for them?

oracle select records today but exclude those which may exist in the previous days

two records should exist in a table in oracle, one is from the request and the other is from the response.
i would like to select all those records from today but the problem is the other pair might be existing from the previous two days or more.
how do i ensure that the records that will be returned are only 1 and will not exist in the previous days
select A.referenceNum, A.datetime, A.Type from table A where A.datetime >= sysdate - 1
To visualize, i would like to select only reference num 789ef.
ReferenceNum DateTime Type
123ab (datetoday) Request
123ab (datetoday) Response
456cd (datetoday) Request
456cd (datetoday-2) Response
789ef (datetoday) Request
You can do it in a single table scan (compared to using NOT EXISTS which will use two table scans) using analytic functions:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( ReferenceNum, DateTime, Type ) AS
SELECT '123ab', SYSDATE, 'Request' FROM DUAL UNION ALL
SELECT '123ab', SYSDATE, 'Response' FROM DUAL UNION ALL
SELECT '456cd', SYSDATE, 'Request' FROM DUAL UNION ALL
SELECT '456cd', SYSDATE - 2, 'Response' FROM DUAL UNION ALL
SELECT '789ef', SYSDATE, 'Request' FROM DUAL;
Query 1:
SELECT ReferenceNum
FROM (
SELECT ReferenceNum,
COUNT( CASE WHEN TRUNC( DateTime ) = TRUNC( SYSDATE ) THEN 1 END )
OVER ( PARTITION BY ReferenceNum ) AS num_today,
COUNT( CASE WHEN TRUNC( DateTime ) <> TRUNC( SYSDATE ) THEN 1 END )
OVER ( PARTITION BY ReferenceNum ) AS num_other_day
FROM table_name t
)
WHERE num_today = 1
AND num_other_day = 0
Results:
| REFERENCENUM |
|--------------|
| 789ef |
Use NOT EXISTS operator
SELECT A.referenceNum, A.datetime, A.Type
from table A
where A.datetime >= sysdate - 1
AND NOT EXISTS (
SELECT null FROM table B
WHERE A.referenceNum = B.referenceNum
AND b.datetime < a.datetime
)
SELECT referenceNum
FROM A A1
WHERE TRUNC(A1.datetime) > TRUNC(sysdate)-1
AND A1.Type = 'Request'
AND NOT EXISTS
(SELECT 1
FROM A
WHERE TRUNC(A.datetime) >= TRUNC(sysdate)-1
AND A.Type = 'Response'
AND A.referenceNum = A1.referenceNum
)

Exists query with not equal running extremly slow

I am trying to modify a query that someone else wrote which is taking a really long time to run. The problem has to do with the <> portion of the exists query. Any idea how this can be changed to run quicker?
SELECT m.level4 center, cc.description, m.employeename, m.empno,
TO_DATE (ct.tsdate, 'dd-mon-yyyy') tsdate, ct.starttime, ct.endtime,
ct.DURATION,
NVL (DECODE (ct.paycode, ' ', 'REG', ct.paycode), 'REG') paycode,
ct.titlecode, ct.costcenter, m.tsgroup
FROM clairvia_text ct, MASTER m, costcenteroutbound cc
WHERE ct.recordtype = '1'
AND ct.empno = m.empno
AND m.level4 = cc.center
AND EXISTS (
SELECT ct1.recordtype,ct1.empno,ct1.tsdate,ct1.processdate
FROM clairvia_text ct1
WHERE ct.recordtype = ct1.recordtype
AND ct.empno = ct1.empno
AND ct.tsdate = ct1.tsdate
AND ct.processdate = ct1.processdate
group by ct1.recordtype,ct1.empno,ct1.tsdate,ct1.processdate
having count(*) < 2)
Oracle can be finnicky with exists statements and subqueries. A couple of things to try:
Change the exists to an "in"
Change the exists to a group by statement with a "having count(1) > 1". This could even be changed into a join.
I'm assuming indexes are not an issue.
You can use analytic function count here to eliminate duplicated rows.
select * from (
SELECT m.level4 center, cc.description, m.employeename, m.empno,
TO_DATE (ct.tsdate, 'dd-mon-yyyy') tsdate, ct.starttime, ct.endtime,
ct.DURATION,
NVL (DECODE (ct.paycode, ' ', 'REG', ct.paycode), 'REG') paycode,
ct.titlecode, ct.costcenter, m.tsgroup,
count(1) over (partition by ct.recordtype,ct.empno,ct.tsdate,ct.processdate
order by null) cnt
FROM clairvia_text ct, MASTER m, costcenteroutbound cc
WHERE ct.recordtype = '1'
AND ct.empno = m.empno
AND m.level4 = cc.center
) where cnt=1
I do not have your structures and data, so I run similar queries with all_tab_cols and first query took ~500s on my laptop and second query ~2s.
-- slow test
select count(1)
from all_tab_cols atc
where exists (
select 1
from all_tab_cols atc1
where atc1.column_name = atc.column_name
group by column_name
having count(1) = 1)
-- fast test
select count(1)
from (
select column_name,
count(1) over (partition by atc.column_name order by null) cnt
from all_tab_cols atc
)
where cnt = 1

Common table expression Alias Name issue

I am trying to insert column values of BREAK_TIME and DIFF_OUT into my base table ezlabor_final_ak using Common Table Expression(CTE) but it is giving error message
ORA-00904: "B"."IN_TIME": invalid identifier'
I am actually giving B as Alias name to my CTE but it is throwing error. Please help in rectifying the error. Please see the below code:
INSERT INTO ezlabor_final_ak(BREAK_TIME,DIFF_IN_OUT)
SELECT BREAK_TIME,DIFF_IN_OUT FROM (
WITH CTE_RN
AS
(
SELECT t.out_time,t.in_time,t.Employee,
ROW_NUMBER() OVER(ORDER BY In_Time) AS RN
FROM ezlabor_final_ak t
WHERE employee = 'JHW004605' AND TO_CHAR(in_time, 'dd/mm/yyyy') = '21/11/2013'
)
SELECT
a.Employee,TO_CHAR(a.in_time,'dd/mm/yyyy hh:mi:ss'),TO_CHAR(a.out_time,'dd/mm/yyyy hh:mi:ss'),a.RN as ARN,
TO_CHAR(p.out_time,'dd/mm/yyyy hh:mi:ss'),TO_CHAR(p.in_time,'dd/mm/yyyy hh:mi:ss'),p.RN AS PRN,
(a.in_time - p.out_time)*24*60 AS BREAK_TIME,
(a.OUT_TIME - a.IN_TIME)*24*60 AS DIFF_IN_OUT
FROM CTE_RN a
LEFT JOIN CTE_RN p
ON p.EMPLOYEE = a.EMPLOYEE AND
p.RN = a.RN - 1
WHERE a.employee = 'JHW004605' AND TO_CHAR(a.in_time, 'dd/mm/yyyy') = '21/11/2013'
) b
WHERE b.employee = 'JHW004605' AND TO_CHAR(b.in_time, 'dd/mm/yyyy') = '21/11/2013'

REGEXP_SUBSTR to update a table

I am trying to use REGEXP_SUBSTR to update a column in a table and I am getting the error, missing expression.
UPDATE p_table SET f_name = SELECT REGEXP_SUBSTR ( (SELECT user_name
FROM user_info
WHERE ROWID = R_ID ('user_info')), '[^ ]{1,15}', 1, 1)
FROM DUAL;
When I add parentheses before the first select and after dual it works but sets all the rows in that column to the same value. I do not need them all to be unique but I cannot have them all the same. Thanks for any advice you could give me.
UPDATE p_table SET f_name = (SELECT REGEXP_SUBSTR ( (SELECT user_name
FROM user_info
WHERE ROWID = R_ID ('user_info')), '[^ ]{1,15}', 1, 1)
FROM DUAL);
As mentioned in #PatrickMarchand comment Oracle optimizes query, so your function called only once. AskTom article makes it clear.
To get a workaround you must introduce something linked to p_table rows into function parameters to force Oracle call it for every row.
For example rowid from p_table:
UPDATE p_table
SET f_name = (
SELECT
REGEXP_SUBSTR(
( SELECT user_name FROM user_info
WHERE ROWID = R_ID ('user_info', p_table.rowid)
),
'[^ ]{1,15}', 1, 1
)
FROM DUAL
)
SQLFiddle example.
Does it do what you want without the subquery?
UPDATE p_table
SET f_name = (SELECT REGEXP_SUBSTR(user_name, '[^ ]{1,15}', 1, 1)
FROM user_info
WHERE ROWID = R_ID ('user_info')
);

Resources