Oracle ORA-00904 error: invalid identifier - oracle

I am quite new to using Oracle. I am running a procedure to update a table. The procedure basically uses a table name and a column name as a parameter.
I am getting an ORA-00904. I looked into the error messages and researched about it, and found that my column names that I am passing might not be correct (accepted values are: less than or equal to 30 characters / alphanumeric and special characters $, _, and #)
My error message is:
Error in UV_KVS_EXTRACT_VALIDATION, error: ORA-00904: "CIT_DW_ETL"."TO_NUMBER_VALIDATE": invalid identifier, sql= select distinct uv.FRM_TRACK_ID, uv.INST_NUM, uv.TPST_SRV_CONTACT_DTE uv_value, k.value kvs_value, 'KVS_EVENT_DATA' kvs_table, k.event_id kvs_id from IM_FORMS.FRM_2450_UV_mv uv join iidb_stg.fn_frm_track_mv frm on uv.FRM_TRACK_ID = frm.frm_track_id and frm.STS_CDE in ('AER','AIP','AUD','CMP','PND','QRY') join cit_udm.event e on uv.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, '$.ID1')) and uv.INST_NUM = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, '$.ID2')) join cit_udm.KVS_EVENT_DATA k on k.event_id = e.event_id where k.key = 'TPST_SRV_CONTACT_DTE'
For example, if I follow the above error message, to me it seems that column name TPST_SRV_CONTACT_DTE is incorrect. But it is alphanumeric + less than 30 characters and has _ special character. It follows the format yet it is failing.
Below is the snippet of the procedure which might be failing:
v_sql := 'select distinct uv.FRM_TRACK_ID, uv.INST_NUM, uv.' || v_uv_column || ' uv_value, '||
' k.value kvs_value, ''' || v_kvs_table || ''' kvs_table, k.' || case when v_kvs_table = 'KVS_EVENT_DATA' then 'event_id'
when v_kvs_table = 'KVS_PRODUCT_DATA' then 'product_id' end || ' kvs_id' ||
' from IM_FORMS.' || v_uv_table || '_mv uv' ||
' join iidb_stg.fn_frm_track_mv frm on uv.FRM_TRACK_ID = frm.frm_track_id and frm.STS_CDE in (''AER'',''AIP'',''AUD'',''CMP'',''PND'',''QRY'')' ||
case when v_kvs_table = 'KVS_EVENT_DATA' then
' join cit_udm.event e on uv.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, ''$.ID1'')) and uv.INST_NUM = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, ''$.ID2''))' ||
' join cit_udm.KVS_EVENT_DATA k on k.event_id = e.event_id where k.key = ''' || v_key || ''''
when v_kvs_table = 'KVS_PRODUCT_DATA' then
' join cit_udm.product p on uv.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(p.sys_source_id, ''$.ID1'')) and uv.INST_NUM = cit_dw_etl.to_number_validate(JSON_VALUE(p.sys_source_id, ''$.ID2''))' ||
' join cit_udm.KVS_PRODUCT_DATA k on k.product_id = p.product_id where k.key = ''' || v_key || ''''
else ''
end
;
This v_sql gets used downstream in the code.
I am 90% sure it is something related to the way columns are named and where it might be occurring from, but I am clueless what and how to fix it. Is it something related to changing single quotes to double quotes?
Any comments or suggestions are most welcome.
Thanks.

error: ORA-00904: "CIT_DW_ETL"."TO_NUMBER_VALIDATE"
cit_dw_etl.to_number_validate is a function call, here:
v.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, '$.ID1'))
The error indicates that Oracle can't find the function, most likely because you don't have permission to see or execute it, or because the function hasn't been created.

I guess that your problem is in this part kvs_value, 'KVS_EVENT_DATA' kvs_table,. If you remove the 'KVS_EVENT_DATA' then it will work. I do not know what you are trying to get here.

Related

How to join 2 tables in PLSQL in ORACLE APEX

I am trying to create a form with dynamic region for purposes of printing. I have a simple PLSQL that works:
declare
cursor c_VYDEJKY is
select ID, INFO, CUSTOMER_ID
from VYDEJKY
where ID = :P54_NEW;
begin
sys.htp.p('<ul>');
for a in c_VYDEJKY loop
sys.htp.p('<li>' || a.ID || ' (' || a.CUSTOMER_ID || ')</li>' );
end loop;
sys.htp.p('</ul>');
end;
but when I try to join another table with LEFT JOIN or WHERE clause it doesnt work:
declare
cursor c_VYDEJKY is
select v.ID, v.INFO, v.CUSTOMER_ID, c.CUSTOMERNAME
from VYDEJKY v, CUSTOMERS c
where v.ID = :P54_NEW
AND v.CUSTOMER_ID > c.ID;
begin
sys.htp.p('<ul>');
for a in c_VYDEJKY loop
sys.htp.p('<li> ID VÝDEJKY :' || a.ID ||'</li>' );
sys.htp.p('<li> POZNÁMKY :' || a.INFO ||'</li>' );
sys.htp.p('<li> POZNÁMKY :' || c.CUSTOMERNAME ||'</li>' );
end loop;
sys.htp.p('</ul>');
end;
I am getting following error on c.CUSTOMERNAME
ORA-06550: line 15, column 39: PLS-00201: identifier 'C.CUSTOMERNAME' must be declared
Can someone please point to where I am makiing a mistake. I am really just starting with PLSQL.
Thank you,
JJ
Within the for loop, the prefix for the column names refers to the cursor row variable (for a in) not the table alias, so you need to specify:
a.CUSTOMERNAME

Rewriting SQL statement into PL/SQL

I am trying to rewrite a SQL statement in PL/SQL but I am new to this and I can't get it right.
This is the original statement:
select f.flugnummer, p.nachname, pl.sitzplatznummer, l.bezeichnung, r.reisepassnr,
sum(g.gewicht) as Luggage
from passagierliste pl join flug f on f.flugID = pl.flugID
join gepaeck g on pl.personID = g.personID
join person p on pl.personID = p.personID
join reisepass r on p.personID = r.personID
join land l on r.landID = l.landID
where f.flugnummer ='AF3012'and pl.sitzplatznummer = '13'
group by f.flugnummer, p.nachname, pl.sitzplatznummer, l.bezeichnung, r.reisepassnr;
And this is my attempt in PL/SQL where I am trying to return a passenger who is on the flight AF3012 and seat 13:
CREATE OR REPLACE PROCEDURE getPassenger IS
v_flugnummer varchar2(30);
v_sitzplatz varchar2(30);
BEGIN
v_flugnummer := 'AF3012';
v_sitzplatz := '13';
select f.flugnummer, p.nachname into v_nachname, pl.sitzplatznummer, l.bezeichnung, r.reisepassnr into v_reisepassnr,
sum(g.gewicht) as Luggage into v_luggage
from passagierliste pl join flug f on f.flugID = pl.flugID
join gepaeck g on pl.personID = g.personID
join person p on pl.personID = p.personID
join reisepass r on p.personID = r.personID
join land l on r.landID = l.landID
where f.flugnummer =v_flugnummer and pl.sitzplatznummer = v_sitzplatz
group by f.flugnummer, p.nachname, pl.sitzplatznummer, l.bezeichnung, r.reisepassnr;
IF v_sitzplatz > 0 THEN
DBMS_OUTPUT.PUT_LINE(v_nachname || ' ' || v_flugnummer || ' ' || v_sitzplatz || ' ' || v_reisepassnr || ' ' || v_luggage);
ELSE
DBMS_OUTPUT.PUT_LINE( '0');
END IF;
COMMIT;
END;
/
exec getPassenger;
A little bit simplified (as I removed unnecessary columns your SELECT returned), this is what might work.
don't hardcode parameters; pass them into the procedure for more flexibility
every column select returns has to have its own variable to put that value into. You can't select e.g. 10 columns into e.g. 2 variables; that just won't work
if query doesn't return anything, it'll raise NO_DATA_FOUND you should handle
create or replace procedure getpassenger (par_flugnummer in varchar2,
par_sitzplatz in varchar2
)
is
v_nachname person.nachname%type;
begin
-- find the passenger
select p.nachname
into v_nachname
from passagierliste pl join flug f on f.flugid = pl.flugid
join gepaeck g on pl.personid = g.personid
join person p on pl.personid = p.personid
join reisepass r on p.personid = r.personid
join land l on r.landid = l.landid
where f.flugnummer = par_flugnummer
and pl.sitzplatznummer = par_sitzplatz;
-- passenger has been found - display it
dbms_output.put_line(v_nachname || ' ' || par_flugnummer || ' ' || par_sitzplatz);
exception
when no_data_found then
-- passenger hasn't been found so previous SELECT returned
-- NO_DATA_FOUND; handle it
dbms_output.put_line('Nobody sits there');
end;
/
exec getpassenger(par_flugnummer => 'AF3012', par_sitzplatz => '13');

execute immediate missing right parentheses error

I have code like below in my procedure. When I call the procedure, there is missing right parentheses error. When I test it outside the procedure, with no execute immediate clause, it works fine.
Would anyone help me pls to eliminate the mistake?
EXECUTE IMMEDIATE '
INSERT INTO prehledcen
(id_obchodu
,id_obchodu_poradi
,smer
,typceny
,vzdalenost
,hodnotaceny
,kid)
SELECT a.id_obchodu
,a.id_obchodu_poradi
,smer
,''PredchoziLast''
,predchozi_last_time - datum_obchodu
,predchozi_last
,kid
FROM middle_office.f_d_obchody_zmeny_test a
INNER JOIN (SELECT id_obchodu
,id_obchodu_poradi
,MAX(dwh_insert_process) dwh_insert_process
,MIN(insert_sysdate) insert_sysdate
FROM middle_office.f_d_obchody_zmeny_test b
GROUP BY id_obchodu
,id_obchodu_poradi) b
ON b.id_obchodu = a.id_obchodu
AND b.id_obchodu_poradi = a.id_obchodu_poradi
AND a.dwh_insert_process = b.dwh_insert_process
WHERE (datum_obchodu >= ' || v_datum_od || ' OR
(datum_obchodu < ' || v_datum_od || ' AND b.insert_sysdate >= ' || v_datum_od || '))';
I assume you have bad values for v_datum_od. Try this one:
EXECUTE IMMEDIATE '
INSERT INTO prehledcen
...
WHERE (datum_obchodu >= :d1 OR (datum_obchodu < :d2 AND b.insert_sysdate >= :d3))'
USING v_datum_od, v_datum_od, v_datum_od;

Error in pl/sql block has me stuck - Number and/or types of columns in a query does not match

Not quite sure what I am doing wrong here, went over the code a few times tonight and I think I need a fresh set of eyes. I keep getting an error that states:
*Cause: Number and/or types of columns in a query does not match declared
return type of a result set variable, or declared types of two Result
Set variables do not match.
*Action: Change the program statement or declaration. Verify what query the variable
actually refers to during execution.
DECLARE
cv_prod SYS_REFCURSOR;
rec_payment dd_payment%ROWTYPE;
TYPE pay2 IS RECORD (
pledge_id dd_pledge.idpledge%TYPE,
amount NUMBER(8,2)
);
rec_payment2 pay2;
lv_donor_id dd_donor.iddonor%TYPE := 303;
lv_indicator_value CHAR(1) := 'd';
BEGIN
IF lv_indicator_value = 'd' THEN
OPEN cv_prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge inner join dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
ORDER BY idpledge, paydate;
LOOP
FETCH cv_prod INTO rec_payment;
EXIT WHEB cv_prod%NOTFOUND;
dbms_output.put_line(rec_payment.idpledge || ' ' || rec_payment.payamt || ' ' || rec_payment.paydate || ' ' || rec_payment.paymethod);
END LOOP;
ELSIF Lv_Indicator_Value = 's' THEN
OPEN cv_Prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge INNER JOIN dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
GROUP BY idpledge;
LOOP
FETCH cv_prod INTO rec_payment2;
EXIT WHEN cv_prod%NOTFOUND;
dbms_output.put_line(rec_payment2.pledge_id || ' ' || rec_payment2.amount);
END LOOP;
END IF;
END;
You're collecting the fields selected by your query into a record which doesn't have the same number and type of fields of your query.
For example, in your second cursor you're selecting the fields idpledge, payamt, paydate, paymethod:
OPEN cv_prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge INNER JOIN dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
GROUP BY idpledge;
And you're trying to put them into the rec_payment2 record:
FETCH cv_prod INTO rec_payment2;
But the type of this record is pay2, which is a record with only two fields:
TYPE pay2 IS RECORD (
pledge_id dd_pledge.idpledge%TYPE,
amount NUMBER(8,2)
);

Insertion from cursor failing due to data error, How to find the problematic data?

I have cursor which is selecting data and it is running quite fine
CURSOR Crs_c1 IS
SELECT a.GLOBAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_NAME,
c.GLOBAL_ACCOUNT_TYPE t_conto,
ltrim(rtrim(a.GLOBAL_ACCOUNT_CODE))||ltrim(rtrim(a.LOCAL_ACCOUNT_CODE)) GLOBAL_LOCAL
FROM V_LOCAL_ACCOUNTS#GDW_LIVE a,V_GLOBAL_ACCOUNTS#GDW_LIVE c --V_LOCAL_ACCOUNTS#GDWPP_ANY a,V_GLOBAL_ACCOUNTS#GDWPP_ANY c
WHERE a.enabled_flag = 'Y'
AND a.GLOBAL_ACCOUNT_CODE=c.GLOBAL_ACCOUNT_CODE
AND not exists (SELECT 1
FROM conto_gdw b -- considero solo i conti nuovi
WHERE a.LOCAL_ACCOUNT_CODE = b.c_conto_local_gdw
AND a.GLOBAL_ACCOUNT_CODE=b.C_CONTO_GLOBAL_GDW);
But at the time of insertion the code fails....
INSERT INTO conto_gdw
(C_CONTO_LOCAL_GDW,
S_CONTO_LOCAL_GDW,
C_CONTO_GLOBAL_GDW,
T_CONTO,
D_INIZIO,
GLOBAL_LOCAL)
VALUES (Rec_Crs_c1.LOCAL_ACCOUNT_CODE,
nvl(Rec_Crs_c1.LOCAL_ACCOUNT_NAME,'.'),
Rec_Crs_c1.GLOBAL_ACCOUNT_CODE,
Rec_Crs_c1.t_conto,
(v_anno_in * 100) + v_mese_in,
Rec_Crs_c1.GLOBAL_LOCAL);
May be this problem is occuring because of a single tuple (dataset). How can I find that culprit data?
I have checked all the data from cursor selection by taking it in a excel sheet, I could not find anything manually. Is there any way ORACLE would return me the failed data?
You need to have a proper exception handling while inserting data .Provide the output of the pl sql block .After than we can help you.
DECLARE
CURSOR Crs_c1
IS
SELECT a.GLOBAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_NAME,
c.GLOBAL_ACCOUNT_TYPE t_conto,
LTRIM (RTRIM (a.GLOBAL_ACCOUNT_CODE))
|| LTRIM (RTRIM (a.LOCAL_ACCOUNT_CODE))
GLOBAL_LOCAL
FROM V_LOCAL_ACCOUNTS#GDW_LIVE a, V_GLOBAL_ACCOUNTS#GDW_LIVE c
WHERE a.enabled_flag = 'Y'
AND a.GLOBAL_ACCOUNT_CODE = c.GLOBAL_ACCOUNT_CODE
AND NOT EXISTS
(SELECT 1
FROM conto_gdw b -- considero solo i conti nuovi
WHERE a.LOCAL_ACCOUNT_CODE = b.c_conto_local_gdw
AND a.GLOBAL_ACCOUNT_CODE =
b.C_CONTO_GLOBAL_GDW);
Rec_Crs_c1 Crs_c1%ROWTYPE;
BEGIN
OPEN Crs_c1;
LOOP
FETCH Crs_c1 INTO Rec_Crs_c1;
EXIT WHEN Crs_c1%NOTFOUND;
INSERT INTO conto_gdw (C_CONTO_LOCAL_GDW,
S_CONTO_LOCAL_GDW,
C_CONTO_GLOBAL_GDW,
T_CONTO,
D_INIZIO,
GLOBAL_LOCAL)
VALUES (Rec_Crs_c1.LOCAL_ACCOUNT_CODE,
NVL (Rec_Crs_c1.LOCAL_ACCOUNT_NAME, '.'),
Rec_Crs_c1.GLOBAL_ACCOUNT_CODE,
Rec_Crs_c1.t_conto,
(v_anno_in * 100) + v_mese_in,
Rec_Crs_c1.GLOBAL_LOCAL);
END LOOP;
CLOSE Crs_c1;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error Message' || SQLERRM);
DBMS_OUTPUT.put_line( 'GLOBAL_ACCOUNT_CODE :'
|| Rec_Crs_c1.LOCAL_ACCOUNT_CODE
|| 'LOCAL_ACCOUNT_CODE '
|| Rec_Crs_c1.LOCAL_ACCOUNT_NAME
|| 'GLOBAL_ACCOUNT_CODE :'
|| Rec_Crs_c1.GLOBAL_ACCOUNT_CODE
|| 'GLOBAL_ACCOUNT_TYPE '
|| Rec_Crs_c1.t_conto
|| 'GLOBAL_LOCAL'
|| Rec_Crs_c1.GLOBAL_LOCAL);
END;

Resources