I'm trying to do a select and I get an ORA-06533 subcript beyond count.
I don't understand why is this error because there are no subscripts in the select.
I post the relevant code:
TYPE Item IS RECORD (
entity number,
period number,
value NUMBER);
TYPE ItemSet IS TABLE OF Item;
modelo_pd ItemSet;
select id_scenario into sid from sae_lc_scen_var where us_type = num and type = 0 and id_segment = pid;
str := 'select distinct bd.entity_id, v.period_id, v.number_attribute_46 pd_pit
from sae_scenario s, sae_baseline b, sae_baseline_data bd, sae_entity e, v_sae_scenario_data v
where s.id = ' || sid || ' and b.scenario_type = s.scenario_type and b.id = bd.baseline_id
and bd.entity_id = e.id and b.id = s.baseline_id and v.scenario_id = s.id and v.baseline_id = b.id
and e.string_attribute_1 = ''' || t.name || ''' and v.e_string_attribute_1 = e.string_attribute_1';
execute immediate str bulk collect into modelo_pd;
The parameters for the query are from two other queries:
select id_scenario into sid from sae_lc_scen_var where us_type = num and type = 0 and id_segment = pid;
and the loop:
for t in (select v.id_segment, s.name, v.value expert, v.value3 selection, v.value2 correction from sae_lc_scen_var v, sae_lc_segments s
where v.us_type = 1 and v.type = 0
and s.id = v.id_segment and v.value <> 0)
The error raises in the dynamic select. That is in execute immediate str bulk collect into modelo_pd;
Any clue?
The full thing:
num := get_constant('US_TYPE_EAD_AGGREGATE');
for t in (select v.id_segment, s.name, v.value expert, v.value3 selection, v.value2 correction from sae_lc_scen_var v, sae_lc_segments s
where v.us_type = 1 and v.type = 0
and s.id = v.id_segment and v.value <> 0)
loop
-- value3: 0=Model, 1=Proxy VMG, 2=Expert, 3=PD_TTC
num := get_constant('US_TYPE_LGD_CALC_METHOD');
if t.selection = 0 then
num := get_constant('US_TYPE_MODELOS_PD');
select id_scenario into sid from sae_lc_scen_var where us_type = num and type = 0 and id_segment = pid;
str := 'select distinct bd.entity_id, v.period_id, v.number_attribute_46 pd_pit
from sae_scenario s, sae_baseline b, sae_baseline_data bd, sae_entity e, v_sae_scenario_data v
where s.id = ' || sid || ' and b.scenario_type = s.scenario_type and b.id = bd.baseline_id
and bd.entity_id = e.id and b.id = s.baseline_id and v.scenario_id = s.id and v.baseline_id = b.id
and e.string_attribute_1 = ''' || t.name || ''' and v.e_string_attribute_1 = e.string_attribute_1';
execute immediate str bulk collect into modelo_pd;
I've found the source of the error.
There is no rows for that select so when I use modelo_pd it gives that error.
What is unclear for me is why it is giving the line number way before the subscript is used.
Related
I have the below query once I run it, it's exceeded successfully without error, but when I run it inside a procedure, I got the single error.
CREATE OR REPLACE PROCEDURE ABLEA_NEW.AB_VATFILE
IS
fHandle UTL_FILE.FILE_TYPE;
err varchar2(200);
v_str VARCHAR2(4000);
CURSOR VAT1 IS
SELECT (SELECT cif_no
FROM nbfc_customer_m
WHERE customerid = a.bpid) ||
(SELECT EXTRACT_ACCT(HOST_ACCT_INFO, 'SUFFIX')
FROM LEA_AGREEMENT_GROUPGL_MAP A, FA_ACCTCATG_M B
WHERE EXTRACT_ACCT(A.HOST_ACCT_INFO, 'ACCTCATG') = B.ACCTCATG
AND B.GROUPID = 'FA'
AND A.ACTIVE_FLAG = 'Y'
and AGREEMENTID = a.caseid)
"Account No",lpad(a.caseid,6,0) Loan_No
,
(SELECT AGREEMENTNO
FROM lea_agreement_dtl
WHERE AGREEMENTID = a.caseid)
AGREEMENTNO
,
LPAD(A.productid,3,0) Scheme_ID,
(SELECT rpad(schemedesc,35,' ')
FROM lea_scheme_m
WHERE schemeid = a.productid)
SchemeDesc,
to_char(a.advicedate,'ddmmyyyy') advicedate,
it_conv(a.adviceamt) adviceamt,
rpad(a.chargeid,6,' ')chargeid,
(SELECT rpad(chargedesc,35,' ')
FROM nbfc_charges_m
WHERE chargeid = a.chargeid)
"Charge Description",
IT_CONV(a.chargeamt)chargeamt,
(SELECT
decode(count(1),0,'N','Y')
FROM nbfc_pmnt_dtl y
WHERE a.txnadviceid = y.txnadviceid
AND a.status = 'A'
AND y.status IS NULL
--and TRUNC(y.pmntdate) between :p_datefrom and :p_dateto
AND a.tax_applicable = 'Y'
AND a.ptxnadviceid IS NULL)Paid,
LPAD(b.chargeid,6,0)
"VAT ChargeID",
(SELECT RPAD(chargedesc,35,' ')
FROM nbfc_charges_m
WHERE chargeid = b.chargeid)
"VAT Charge Description",
IT_CONV(b.chargeamt)
"VAT Amount"
FROM (SELECT *
FROM nbfc_txn_advice_dtl
WHERE status = 'A' AND tax_applicable = 'Y' AND ptxnadviceid IS NULL)
a,
(SELECT *
FROM nbfc_txn_advice_dtl
WHERE status = 'A' AND ptxnadviceid IS NOT NULL) b
WHERE a.txnadviceid = b.ptxnadviceid;
BEGIN
fHandle := UTL_FILE.FOPEN('UAEDB', 'VAT', 'W');
FOR I IN VAT1
LOOP
v_str:= null;
v_str:= I."Account No"||I.Loan_No||I.AGREEMENTNO || I.Scheme_ID ||I.SchemeDesc|| I.advicedate|| I.adviceamt|| I.chargeid||I."Charge Description"||I.chargeamt||I.Paid||
I."VAT ChargeID" ||I."VAT Charge Description"||I."VAT Amount";
UTL_FILE.PUTF(fHandle,v_str);
UTL_FILE.PUTF(fHandle, '\n');
END LOOP;
UTL_FILE.FCLOSE(fHandle);
END ;
/
How can I solve this?
Note: the query return mor than 10000 record.
comment or un-comment the "(select from )as ColumnAlias" query column one by one, you can find which sub query column return more than one row
Select
c.id AS case_id,
c.id AS case_number,
tt.description as Target_Type,
coalesce(
v_vendors.vendor_number,
vma.org_code,
TO_CHAR(sm.staff_member_id),
la.org_code,
oe.other_fns_number,
TO_CHAR(oe.other_id),
TO_CHAR(c_clients.client_id)
) as Target_Identifier,
coalesce(
v_vendors.vendor_name,
vma.name,
s_wic_users.username,
la.name,
oe.other_name,
UPPER(
c_clients.last_name || ', ' || c_clients.first_name
)
) as Target_Name,
c.date_opened AS Open_Date,
c.date_closed AS Close_Date,
t.target_type_id,
t.target_id,
s.description AS Status,
case when aIosm.last_name is null then '' else UPPER(
aIosm.last_name || ', ' || aIosm.first_name
) end Investigator,
case when aSosm.last_name is null then '' else UPPER(
aSosm.last_name || ', ' || aSosm.first_name
) end Supervisor,
c.Notes AS Supervisor_Comments,
aI.Date_Assigned as Assign_Date,
----subquery starts
(
select
lat.description
from
investigation_actions_taken iat
join investig_lu_action_type lat on iat.action_type_id = lat.id
where
iat.investigation_case_id = c.id
and iat.is_deleted <> 'T'
order by
iat.date_assessed desc,
iat.date_created desc OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
) AS Last_Action
from
v_investigation_cases c
join investigation_target t on c.target_id = t.target_id
join v_lu_inv_status s on (
case when date_closed <= TRUNC(sysdate) then 2 else case when date_opened > TRUNC(sysdate) then 2 else 1 end end
) = s.status_id
join investigation_target_type tt on t.target_type_id = tt.target_type_id
---left join starts
left join investigation_case_assignment aI on c.id = aI.investigation_case_id
and aI.date_roll_off is null
and aI.assignment_type = 'I'
left join o_staff_members aIosm on aI.staff_member_id = aIosm.staff_member_id
left join investigation_case_assignment Super on c.id = Super.investigation_case_id
and Super.date_roll_off is null
and Super.assignment_type = 'S'
left join o_staff_members aSosm on Super.staff_member_id = aSosm.staff_member_id
-----left join starts
left join v_vendors on t.vendor_id = v_vendors.id
left join o_organizational_units vma on t.vendor_management_area_id = vma.seq_id
left join c_clients on t.client_id = c_clients.client_id
left join o_staff_members sm on t.user_id = sm.staff_member_id
left join s_wic_users on sm.staff_member_id = s_wic_users.sm_staff_member_id
left join investigation_other_entity oe on t.non_wic_vendor_id = oe.other_id
left join o_organizational_units la on t.local_agency_id = la.seq_id
---end of the query
Here's an article about what you can achieve in Oracle 12c with the OFFEST FETCH based on Kaushik Nayak.
http://www.dba-oracle.com/t_offset_fet_first_rows_only.htm
I hope it can help you to convert your original query to 11g. Good luck.
I'm trying to convert the Oracle Sql query below to linq, without much success. I'm not sure how to handle the line AND ShipSeq = i.ShipSeq(+), which I've learned is a LEFT OUTER JOIN in Oracle. I'm testing the Linq query below in LinqPad, where I don't get any syntax errors but it errors on executing the query. Any ideas?
Oracle Sql Query
SELECT *
FROM CustomerShip,
(SELECT DISTINCT b.ShipSeq AS shipSeq
FROM Orders a,
CustomerShip b
WHERE a.OrderId IN (SELECT OrderId
FROM Orders
WHERE CustomerId = #CustomerId
AND OrderType <> 'A')
AND b.CustomerId = #CustomerId
AND b.ShipSeq = a.CustShip
AND OrderStatus <> 'C'
GROUP BY b.ShipSeq) i
WHERE CustomerId = #CustomerId
AND (Address NOT LIKE '%RETAIL%STORE%')
AND ShipSeq = i.ShipSeq(+)
ORDER BY ShipTo DESC, OrderDate DESC;
Linq Query
var query = from s in CustomerShip
join m in Orders on s.ShipTo equals m.ShipTo into temp
from x in temp.DefaultIfEmpty()
where (from o in Orders
from c in CustomerShip
where (from x in CustomerOrders
where x.CustomerId == customerId
&& !x.OrderType.Equals("A")
select x.OrderId).Contains(o.OrderId)
&& c.CustomerId == customerId
&& c.ShipTo == o.ShipTo
&& !o.OrderStatus.Equals("C")
select c.ShipTo).Distinct().Contains(s.ShipTo)
&& s.CustomerId == customerId
&& !s.Address.Contains("RETAIL")
&& !s.Address.Contains("STORE")
orderby s.ShipTo descending, s.OrderDate descending
select s;
I think a literal translation looks like this:
var iQuerySub = from o in Orders where o.CustomerId == pCustomerId && o.OrderType != "A" select o.OrderId;
var iQuery = (from a in Orders
from b in CustomerShip
where iQuerySub.Contains(a.OrderId) &&
b.CustomerId == pCustomerId &&
b.ShipSeq == a.CustShip &&
a.OrderStatus != "C"
group b by b.ShipSeq into bg
select new { shipSeq = bg.Key }).Distinct();
var ans = from s in CustomerShip
where s.CustomerId == pCustomerId &&
(!s.Address.Contains("RETAIL") || !s.Address.Contains("STORE") || s.Address.IndexOf("RETAIL") > s.Address.IndexOf("STORE"))
join i in iQuery on s.ShipSeq equals i.shipSeq into ij
from i in ij.DefaultIfEmpty()
orderby s.ShipTo, s.OrderDate descending
select new { s, shipSeq = (i != null ? i.shipSeq : (int?)null) };
But both the SQL and LINQ seem inefficient to me, but without domain knowledge this is all I could optimize:
var iQuery2 = (from b in CustomerShip
where b.CustomerId == pCustomerId &&
Orders.Any(a => a.CustomerId == pCustomerId && a.OrderType != "A" && a.OrderStatus != "C" && b.ShipSeq == a.CustShip)
select new { shipSeq = b.ShipSeq }).Distinct();
var ans2 = from s in CustomerShip
where s.CustomerId == pCustomerId &&
(!s.Address.Contains("RETAIL") || !s.Address.Contains("STORE") || s.Address.IndexOf("RETAIL") > s.Address.IndexOf("STORE"))
join i in iQuery2 on s.ShipSeq equals i.shipSeq into ij
from i in ij.DefaultIfEmpty()
orderby s.ShipTo, s.OrderDate descending
select new { s, shipSeq = (i != null ? i.shipSeq : (int?)null) };
this is my first time posting, so I am sure I will get a number of things wrong. Do not hesitate to correct me and I will do everything I can to clarify.
In Oracle SQL Developer, I am trying to take two separate SELECT statements and combine them to get one row of results. Unfortunately, because this is sensitive data, I am unable to give any results from the statements individually, but instead, just the SQL statements themselves. I suspect I should be able to join these two on the field "emplid" but just cannot get there. Any help is greatly appreciated! Here is the code below, please mind the syntax :)
1st Select statement is giving me a list of people that were paid in 2017:
SELECT DISTINCT C.COMPANY,
C.EMPLID,
C.SSN
FROM PS_PAY_CHECK C
WHERE TO_CHAR(C.CHECK_DT,'YYYY') = '2017'
AND C.COMPANY IN ('001','054','076')
ORDER BY C.COMPANY, C.EMPLID
And 2nd Select statement would be a list of the deductions taken for the employees that were identified in the first statement:
SELECT G.EMPLID, G.DEDCD,
CASE
WHEN DC.DED_CLASS IN ('A','B','T')
THEN G.DED_ADDL_AMT
ELSE 0
END AS "EEAmt",
CASE
WHEN DC.DED_CLASS NOT IN ('A','B','T')
THEN G.DED_ADDL_AMT
ELSE 0
END AS "ERAmt",
DC.DED_CLASS,
G.DED_ADDL_AMT,
G.GOAL_AMT
FROM PS_GENL_DEDUCTION G,
PS_DED_CLASS_VW DC
WHERE G.EFFDT =
(SELECT MAX(G_ED.EFFDT)
FROM PS_GENL_DEDUCTION G_ED
WHERE G.EMPLID = G_ED.EMPLID
AND G.COMPANY = G_ED.COMPANY
AND G.DEDCD = G_ED.DEDCD
AND G_ED.EFFDT <= SYSDATE
)
AND ( G.DEDUCTION_END_DT IS NULL
OR G.DEDUCTION_END_DT > SYSDATE)
AND ( G.GOAL_AMT = 0.00
OR G.GOAL_AMT <> G.GOAL_BAL)
AND G.DED_ADDL_AMT > 0
AND DC.PLAN_TYPE = '00'
AND DC.DEDCD = G.DEDCD
AND DC.EFFDT =
(SELECT MAX(V1.EFFDT)
FROM PS_DED_CLASS_VW V1
WHERE V1.PLAN_TYPE = DC.PLAN_TYPE
AND V1.DEDCD = DC.DEDCD
)
AND G.EMPLID = 'XXXXXX'
Ideally, what I'd like to do is put in a value in place of 'XXXXXX' and get one row of data with the two combined statements.
Thanks everyone!
To do this, we stick each SELECT statement into a subquery and give that subquery an alias to refer to in the main queries select statement:
SELECT t1.*, t2.*
FROM
(
SELECT DISTINCT C.COMPANY,
C.EMPLID,
C.SSN
FROM PS_PAY_CHECK C
WHERE TO_CHAR(C.CHECK_DT,'YYYY') = '2017'
AND C.COMPANY IN ('001','054','076')
ORDER BY C.COMPANY, C.EMPLID
) t1
INNER JOIN
(
SELECT G.EMPLID, G.DEDCD,
CASE
WHEN DC.DED_CLASS IN ('A','B','T')
THEN G.DED_ADDL_AMT
ELSE 0
END AS "EEAmt",
CASE
WHEN DC.DED_CLASS NOT IN ('A','B','T')
THEN G.DED_ADDL_AMT
ELSE 0
END AS "ERAmt",
DC.DED_CLASS,
G.DED_ADDL_AMT,
G.GOAL_AMT
FROM PS_GENL_DEDUCTION G,
PS_DED_CLASS_VW DC
WHERE G.EFFDT =
(SELECT MAX(G_ED.EFFDT)
FROM PS_GENL_DEDUCTION G_ED
WHERE G.EMPLID = G_ED.EMPLID
AND G.COMPANY = G_ED.COMPANY
AND G.DEDCD = G_ED.DEDCD
AND G_ED.EFFDT <= SYSDATE
)
AND ( G.DEDUCTION_END_DT IS NULL
OR G.DEDUCTION_END_DT > SYSDATE)
AND ( G.GOAL_AMT = 0.00
OR G.GOAL_AMT <> G.GOAL_BAL)
AND G.DED_ADDL_AMT > 0
AND DC.PLAN_TYPE = '00'
AND DC.DEDCD = G.DEDCD
AND DC.EFFDT =
(SELECT MAX(V1.EFFDT)
FROM PS_DED_CLASS_VW V1
WHERE V1.PLAN_TYPE = DC.PLAN_TYPE
AND V1.DEDCD = DC.DEDCD
)
AND G.EMPLID = 'XXXXXX'
) t2 ON
t1.empid = t2.empid
We just treat each derived table/subquery as it's own table and join them on empid. You can tweak the SELECT statement at the top as needed.
This is similar to creating a view for both sql statements and then referencing the views in a third sql statement.
An alternative way of doing this is to use CTE (Common Table Expressions) to house the separate sql. There's no performance advantage here, but you might find it easier to read.
WITH t1 as
(
SELECT DISTINCT C.COMPANY,
C.EMPLID,
C.SSN
FROM PS_PAY_CHECK C
WHERE TO_CHAR(C.CHECK_DT,'YYYY') = '2017'
AND C.COMPANY IN ('001','054','076')
ORDER BY C.COMPANY, C.EMPLID
),
t2 AS
(
SELECT G.EMPLID, G.DEDCD,
CASE
WHEN DC.DED_CLASS IN ('A','B','T')
THEN G.DED_ADDL_AMT
ELSE 0
END AS "EEAmt",
CASE
WHEN DC.DED_CLASS NOT IN ('A','B','T')
THEN G.DED_ADDL_AMT
ELSE 0
END AS "ERAmt",
DC.DED_CLASS,
G.DED_ADDL_AMT,
G.GOAL_AMT
FROM PS_GENL_DEDUCTION G,
PS_DED_CLASS_VW DC
WHERE G.EFFDT =
(SELECT MAX(G_ED.EFFDT)
FROM PS_GENL_DEDUCTION G_ED
WHERE G.EMPLID = G_ED.EMPLID
AND G.COMPANY = G_ED.COMPANY
AND G.DEDCD = G_ED.DEDCD
AND G_ED.EFFDT <= SYSDATE
)
AND ( G.DEDUCTION_END_DT IS NULL
OR G.DEDUCTION_END_DT > SYSDATE)
AND ( G.GOAL_AMT = 0.00
OR G.GOAL_AMT <> G.GOAL_BAL)
AND G.DED_ADDL_AMT > 0
AND DC.PLAN_TYPE = '00'
AND DC.DEDCD = G.DEDCD
AND DC.EFFDT =
(SELECT MAX(V1.EFFDT)
FROM PS_DED_CLASS_VW V1
WHERE V1.PLAN_TYPE = DC.PLAN_TYPE
AND V1.DEDCD = DC.DEDCD
)
AND G.EMPLID = 'XXXXXX'
)
SELECT t1.*, t2.*
FROM t1 INNER JOIN t2 ON
t1.empid = t2.empid
Basically you do something like
select blah, blah.. (your second query )
AND G.EMPLID IN ( SELECT DISTINCT C.COMPANY,
C.EMPLID,
C.SSN
FROM PS_PAY_CHECK C
WHERE TO_CHAR(C.CHECK_DT,'YYYY') = '2017'
AND C.COMPANY IN ('001','054','076')
)
So basically I have used your first query in you second query. I removed the DISTINCT, as its not needed.
I hope that makes sense.
I need to update a list of record given by a subquery, sniffing around on the web I tried this structure:
UPDATE
(
SELECT
a.COL1
FROM
TABLE1 a,
TABLE2 b
WHERE
a.field1 = b.field1
) update_tbl
SET
update_tbl.COL1 = 'VALUE'
But it returns to me this Oracle error:
-> ORA-01779: Cannot modify a column which maps to a non key-preserved table
My query is the following one:
UPDATE
(
SELECT
imp.*
FROM table1 imp
JOIN table2 sp ON imp.id_p = sp.id_p
JOIN table3 cs ON sp.id_s = cs.id_s
JOIN table4 cb ON cb.id_c = cs.id_c
WHERE
imp.id_b = cb.id_b
AND (
(to_char(imp.p,'yyyymm') < to_char(cb.data_in,'yyyymm')) OR
(cb.data_fi IS NOT NULL AND to_char(imp.p,'yyyymm') > to_char(cb.data_fi,'yyyymm'))
)
and (
(imp.v is not null) or
(imp.v_s is not null and imp.v_s <> 0) or
(imp.imp_co is not null and imp.imp_co <> 0) or
(imp.imp_acc is not null and imp.imp_acc <> 0)
)
) i
SET
i.v = null,
i.v_s = 0,
i.imp_co = 0,
i.imp_acc = 0,
i.ID_S_CONT = 'N',
i.ID_T_COMP = 'P',
i.date_upd = SYSDATE,
i.user_upd = 'SeR'
The subquery return 82 rows (tested now), and I do want to modify only that rows, What am I doing wrong?
I think you are updating to imp table. so you can try MERGE like below
MERGE INTO
IMP A
USING
( SELECT
imp.*
FROM table1 imp
JOIN table2 sp ON imp.id_p = sp.id_p
JOIN table3 cs ON sp.id_s = cs.id_s
JOIN table4 cb ON cb.id_c = cs.id_c
WHERE
imp.id_b = cb.id_b
AND (
(to_char(imp.p,'yyyymm') < to_char(cb.data_in,'yyyymm')) OR
(cb.data_fi IS NOT NULL AND to_char(imp.p,'yyyymm') >
to_char(cb.data_fi,'yyyymm'))
)
and (
(imp.v is not null) or
(imp.v_s is not null and imp.v_s <> 0) or
(imp.imp_co is not null and imp.imp_co <> 0) or
(imp.imp_acc is not null and imp.imp_acc <> 0)
)) B
ON (A.ID =B.ID)
WHEN MATCHED THEN
UPDATE SET
A.v = null,
A.v_s = 0,
A.imp_co = 0,
A.imp_acc = 0,
A.ID_S_CONT = 'N',
A.ID_T_COMP = 'P',
A.date_upd = SYSDATE,
A.user_upd = 'SeR'
Will update the table given by subquery. here A.ID =B.ID use the primary key.