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;
Related
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.
I have this instruction
UPDATE TABLE1
SET INC =
(select INC from TABLE2
WHERE KEY = 'KEY_VALUE1'
FETCH FIRST 1 ROW ONLY);
This working fine if i run from sqlPlus or if I use in PLSQL but, if I using in Dynamic SQL, not working
sqlStmt:= 'UPDATE TABLE1'
|| 'SET INC = '
|| '(select INC from TABLE2 '
|| 'WHERE KEY = ''' || v_key_value || ''' '
|| 'FETCH FIRST 1 ROW ONLY); ';
BEGIN
EXECUTE IMMEDIATE sqlStmt;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('{"errorcode":"' || SQLERRM);
ROLLBACK;
END;
This instruction return this error:
{"errorcode":"ORA-00933: comando SQL terminato erroneamente
Someone can you help me?
Regards,
Marco
You don't want to have a semicolon at the end of the string you are building and passing to execute immediate.
It's not the cause of your error. But it would be much kinder to the database to write this using bind variables rather than concatenating literals. Of course, since there is no reason to be using dynamic SQL for this sort of update statement, I'm guessing your actual use case is different and that you are actually using bind variables and/or there is actually a reason why bind variables aren't an option.
OK so I have a cursor for loop that I want to print an error message when the select statement doesn't find a course that the user has inputted. But the problem is that cursor for loops automatically exits when the select statement fails, so my else statement never executes. How do I print a message saying that they course they are looking for doesn't exist. Note switching to a cursor fetch is not an option. For example id the user enters a course that exists it prints all relevant information. When the user inputs a course with no prerequisite it prints a proper message, but if the user inputs a course that doesn't exists, nothing gets printed.
DECLARE
course_name VARCHAR2(40) := '&course_input';
TYPE course_r IS RECORD(
course_description course.description%TYPE,
cost course.cost%TYPE,
prerequisite course.prerequisite%TYPE,
prerequisite_cost course.cost%TYPE
);
course_rec course_r;
CURSOR course_cursor IS
SELECT a.description, a.cost, a.prerequisite, b.cost AS preq_cost
FROM COURSE a
LEFT JOIN COURSE b ON a.prerequisite = b.course_no
WHERE UPPER(a.description) LIKE '%'||'&course_input'||'%';
BEGIN
FOR record IN course_cursor
LOOP
course_rec.course_description := record.description;
course_rec.cost := record.cost;
course_rec.prerequisite := record.prerequisite;
course_rec.prerequisite_cost := record.preq_cost;
IF course_rec.prerequisite IS NULL THEN
DBMS_OUTPUT.PUT_LINE('There is NO prerequisite course for any that starts on ' || course_name || '. Try again');
ELSIF course_rec.prerequisite IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('Course: ' || course_rec.course_description);
DBMS_OUTPUT.PUT_LINE('Cost: ' || course_rec.cost);
DBMS_OUTPUT.PUT_LINE('Prerequisite: ' || course_rec.prerequisite);
DBMS_OUTPUT.PUT_LINE('Prerequisite Cost: ' || course_rec.prerequisite_cost);
DBMS_OUTPUT.PUT_LINE('=================================================');
ELSE
DBMS_OUTPUT.PUT_LINE('There is NO VALID course that starts on '||course_name||'. Try again.');
END IF;
END LOOP;
END;
/
You can do this by having a variable which only gets set inside the loop. Then you can check that variable after the loop has completed to see if it was set, and decide if you need to do additional work.
Something like:
DECLARE
course_name VARCHAR2(40) := '&course_input';
v_rows_present BOOLEAN := FALSE;
BEGIN
FOR course_rec IN (SELECT a.description,
a.cost,
a.prerequisite,
b.cost AS preq_cost
FROM course a
LEFT JOIN course b
ON a.prerequisite = b.course_no
WHERE upper(a.description) LIKE '%' || course_name || '%')
LOOP
v_rows_present := TRUE;
IF course_rec.prerequisite IS NULL
THEN
dbms_output.put_line('There is NO prerequisite course for any that starts on ' || course_name || '. Try again');
ELSE
dbms_output.put_line('Course: ' || course_rec.course_description);
dbms_output.put_line('Cost: ' || course_rec.cost);
dbms_output.put_line('Prerequisite: ' || course_rec.prerequisite);
dbms_output.put_line('Prerequisite Cost: ' || course_rec.prerequisite_cost);
dbms_output.put_line('=================================================');
END IF;
END LOOP;
IF NOT v_rows_present
THEN
dbms_output.put_line('There is NO VALID course that starts on ' || course_name || '. Try again.');
END IF;
END;
/
N.B. I've updated your code as you appear to have misapprehended how to use a cursor for loop.
Cursor-for-loops create their own record variable implicitly, so you don't need to declare one yourself.
You also don't need to declare a cursor explicitly either - that can be done as part of the cursor-for-loop statement.
You don't need to populate a new record with the same values from the cursor-for-loop record in order to use the values (as long as you're using them within the cursor-for-loop, of course!)
You could declare a counter, as say, PLS_INTEGER, initialize it to 0, then increment it inside the loop. After the loop, you can check the value and if it's 0, you know no rows were returned.
THE CURSOR FOR LOOP doesn't execute if there are no such courses in the courses table.So, check if a row exists before entering the loop.
Two other things to note:
LIKE '%'||'&course_input'||'%' is not required in the where clause
as the same variable is already passed from user input and assigned
in the declare section.Simply use LIKE '%' || course_name || '%'
RECORD is a PL/SQL reserved word and shouldn't be used as a loop
index variable, i've changed it to rec.
DECLARE
course_name VARCHAR2(40) := '&course_input';
TYPE course_r IS RECORD ( course_description course.description%TYPE,
cost course.cost%TYPE,
prerequisite course.prerequisite%TYPE,
prerequisite_cost course.cost%TYPE );
course_rec course_r;
cur_count NUMBER;
CURSOR course_cursor IS SELECT a.description,
a.cost,
a.prerequisite,
b.cost AS preq_cost
FROM course a
LEFT JOIN course b ON a.prerequisite = b.course_no
WHERE upper(a.description) LIKE '%' || course_name || '%';
BEGIN
SELECT COUNT(*)
INTO cur_count
FROM course a
WHERE upper(a.description) LIKE '%' || course_name || '%';
IF
cur_count > 0
THEN
FOR rec IN course_cursor LOOP
course_rec.course_description := rec.description;
course_rec.cost := rec.cost;
course_rec.prerequisite := rec.prerequisite;
course_rec.prerequisite_cost := rec.preq_cost;
IF
course_rec.prerequisite IS NULL
THEN
dbms_output.put_line('There is NO prerequisite course for any that starts on ' ||
course_name || '. Try again');
ELSE
dbms_output.put_line('Course: ' || course_rec.course_description);
dbms_output.put_line('Cost: ' || course_rec.cost);
dbms_output.put_line('Prerequisite: ' || course_rec.prerequisite);
dbms_output.put_line('Prerequisite Cost: ' || course_rec.prerequisite_cost);
dbms_output.put_line('=================================================');
END IF;
END LOOP;
ELSE
dbms_output.put_line('There is NO VALID course that starts on ' || course_name || '. Try again.'
);
END IF;
END;
/
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;
Good day. I have a very specific task: regenerate all sequences in database. There is a 400+ tables in it, so I can't do it by hands.
Can somebody help me to do it?
Thanks a lot..
Please note this is highly dangerous. You may very well make mistakes. Run the select first to check what you're about to do and create a table of the select so you can re-create the synonyms manually later if you need to.
Using all_synonyms or dba_synonyms instead of user_synonyms may result in dropping system synonyms do not do this if you want your database to work afterwards
I'd also recommend testing the code on 1 test synonym you create to ensure that it does exactly what you want.
Plus I don't really see the point of doing this at all? If the synonyms are there why do you need to re-generate them? Or is this being done on another server? If so add #server_name after user_synonyms and remove the drop.
begin
for xx in ( select * from user_sequences ) loop
execute immediate 'drop sequence ' || xx.sequence_name;
execute immediate 'create sequence ' || xx.sequence_name
|| ' start with ' || xx.min_value
|| ' ends with ' || xx.max_value
|| case when xx.cycle_flag = 'N' then ' nocycle '
else ' cycle ' end
|| case when xx.cache_size = 0 then ' nocache '
else ' cache ' end || xx.cache_size
|| case when xx.order_flag = 'N' then ' noorder '
else ' order ' end
;
end loop;
end;