How to continue after in Oracle Dynamic SQL - oracle

is it possible to continue after an exception is raised.
I generated a little example of code which is similar to what I would like to perform. I can only get null values from the first query, the other querys always get me something back.
Case Username = InUser Then
Execute Immediate
'select Username from Users where Fullname = ' || '''' || InUser || '''' into Varuser;
<< go_on >>
Execute Immediate
'select Orderno from orders where requester = ' || '''' || VarUser || '''' into VarOrderno
-- other stuff and cases will happen here.
End Case;
EXCEPTION WHEN NO_DATA_FOUND THEN
VarUser := InUser;
Goto go_on;
I know, that if the first dynamic sql doesn't deliver anything, then I use the InUser.
Is there something possible?

Wrap the dynamic select with begin/end and handle the exception there:
Case Username = InUser Then
begin
Execute Immediate
'select Username from Users where Fullname = ' || '''' || InUser || '''' into Varuser;
EXCEPTION WHEN NO_DATA_FOUND THEN
VarUser := InUser;
end;
Execute Immediate
'select Orderno from orders where requester = ' || '''' || VarUser || '''' into VarOrderno
End Case;

Related

Searching for a particular value within an Oracle database

I am trying to search for a particular value within an Oracle database and the script is not working. Can this be done with the following code?
DECLARE
match_count integer;
v_search_string varchar2(4000) := 'QS/Operation';
BEGIN
FOR t IN (SELECT owner,
table_name,
column_name
FROM all_tab_columns
WHERE data_type in ('VARCHAR2') )
LOOP
BEGIN
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '||t.owner || '.' || t.table_name||
' WHERE '||t.column_name||' = :1'
INTO match_count
USING v_search_string;
IF match_count > 0 THEN
dbms_output.put_line( t.owner || '.' || t.table_name ||' '||t.column_name||' '||match_count );
END IF;
EXCEPTION
WHEN others THEN
dbms_output.put_line( 'Error encountered trying to read ' ||
t.column_name || ' from ' ||
t.owner || '.' || t.table_name );
END;
END LOOP;
END;
The script is generating errors. I need to know how to get past the errors and find the value in the tables.
First, catching when others without re-raising is usually a bug; here it looks like you're intending to report errors but carry on, which doesn't seem unreasonable. But you should include the error in the information you display, e.g.:
EXCEPTION
WHEN others THEN
dbms_output.put_line( 'Error encountered trying to read ' ||
t.column_name || ' from ' ||
t.owner || '.' || t.table_name );
dbms_output.put_line(SQLERRM);
END;
Presumably that is telling that tables don't exist, or you have invalid identifiers, or you have privilege errors. You're searching all tables owned by everyone, and not even excluding those owned by SYS as the original code did - hopefully that isn't because you create your own tables under SYS - and it's possible somewhere in there you have tables with quoted identifiers. Actually, it's very likely; SYS has _default_auditing_options_, and system-generated nested table names can be mixed case, for instance.
To be on the safe side adding quotes won't hurt anyway:
BEGIN
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM "' || t.owner || '"."' || t.table_name || '"' ||
' WHERE "' || t.column_name || '" = :1'
INTO match_count
USING v_search_string;

Oracle : Delete rows with "execute immediate" and rowcount

I want to delete rows with an "Execute immediate" because the table name is in a variable.
How can I count the number of lines deleted?
I tried this, but it does not work with the INTO v_LINE_REMOVE;
v_sql := '
DELETE /*+parallel(t,4)*/
FROM "' || v_owner || '"."' || v_table_name ||'" t
where t."'|| v_column_name ||'" in (
select /*+parallel(rem,4)*/
rem.' || v_type_data || '
from ' || v_table_listeremove || ' rem
WHERE rem.dt_vact = '''|| v_dt_vact ||'''
)
';EXECUTE IMMEDIATE v_sql;--INTO v_LINE_REMOVE;
Thanks a lot
You should be able to use SQL%ROWCOUNT after running your DML statement
EXECUTE IMMEDIATE v_sql;
v_line_remove := SQL%ROWCOUNT;

Procedure failed due to ORA-00920: invalid relational operator

Getting below error while executing in 12c oracle,but it is working fine when it was in oracle 10.2.0.4 :
Procedure proc_up_dts_product_cat_dynsql failed due to ORA-00920: invalid
relational operator
Here is the procedure :
CREATE OR REPLACE PROCEDURE SEAPROB.proc_up_dts_product_cat_dynsql(tablename IN varchar)
AS
dynamicsql varchar(8000);
ID int;
DTS_Segment_op varchar2(10);
DTS_Segment varchar2(15);
DTS_Segment_where varchar2(255);
DateEntered_op varchar2(10);
DateEntered varchar2(30);
DateEntered_where varchar2(255);
Svc_Name_op varchar2(10);
Svc_Name varchar2(100);
Svc_Name_where varchar2(255);
Product_Category varchar2(75);
Priority int;
combined_status_where varchar2(255);
refdate date ;
CURSOR PrivCursor
IS
SELECT
ID,
DTS_Segment_op,
Nvl(upper(trim(DTS_Segment)),' '),
DateEntered_op,
CASE WHEN dateentered='%' THEN dateentered
WHEN dateentered LIKE '%/%/____' THEN To_Char(To_Date(dateentered,'MM/DD/YYYY'),'YYYY-MM-DD')
WHEN dateentered LIKE '%/%/__' THEN To_Char(To_Date(dateentered,'MM/DD/YY'),'YYYY-MM-DD')
WHEN dateentered LIKE '''%/%/%'' % ''%/%/%''' THEN ''''||To_Char(To_Date(SubStr(dateentered,InStr(dateentered,'''',1,1)+1,InStr(dateentered,'''',1,2)-InStr(dateentered,'''',1,1)-1),'MM/DD/YY'),'YYYY-MM-DD')||''' and '''||To_Char(To_Date(SubStr(dateentered,InStr(dateentered,'''',1,3)+1,InStr(dateentered,'''',1,4)-InStr(dateentered,'''',1,3)-1),'MM/DD/YY'),'YYYY-MM-DD')||''''
ELSE dateentered END AS dateentered,
Svc_Name_op,
Nvl(upper(trim(Svc_Name)),' '),
Product_Category,
Priority
FROM tbl_dts_pt_lookup order by priority desc;
BEGIN
refdate := ADD_MONTHS(to_date(SYSDATE,'dd-mon-yy'),-6) ;
OPEN PrivCursor;
-- Loop through all the rows in the tbl_dts_category_lookup table
FETCH PrivCursor
INTO
ID,
DTS_Segment_op,
DTS_Segment,
DateEntered_op,
DateEntered,
Svc_Name_op,
Svc_Name,
Product_Category,
Priority;
WHILE PrivCursor%found
LOOP
-- Create dynamic SQL
--define case statements for where clause components
combined_status_where := ' where (DTS_Cm_DisputeStatus <>'|| '''C''' || ' OR ( DTS_Cm_DisputeStatus='|| '''C''' || ' AND DTS_CM_CLOSEDATE >= '''||refdate||'''))' ;
dts_segment_where := case when dts_segment='%' then ' and 1=1' else ' and NVL(trim(Replace(Upper(segment),chr(0),''' || ''')),''' || ' '') ' || dts_segment_op || ' ''' || dts_segment || '''' end;
svc_name_where := case when svc_name='%' then ' and 1=1' else ' and NVL(trim(Replace(Upper(dts_cm_servicename),chr(0),''' || ''')),''' || ' '') ' || svc_name_op || ' ''' || svc_name || '''' end ;
dateentered_where := case when dateentered='%' then ' and 1=1'
when dateentered_op='between' then ' and TO_CHAR(dts_cm_dateentered,''YYYY-MM-DD'') between ' || dateentered
else ' and TO_CHAR(dts_cm_dateentered,''YYYY-MM-DD'') ' || dateentered_op || ' ''' || dateentered || '''' end ;
dynamicsql := 'update '||tablename||' set product_cat_id=' || cast(id as varchar) ||', product_category =''' || product_category || '''';
--add where clause
dynamicsql := dynamicsql || combined_status_where || dts_segment_where || dateentered_where || svc_name_where;
EXECUTE IMMEDIATE dynamicsql;
COMMIT;
FETCH PrivCursor
INTO
ID,
DTS_Segment_op,
DTS_Segment,
DateEntered_op,
DateEntered,
Svc_Name_op,
Svc_Name,
Product_Category,
Priority;
END LOOP;
CLOSE PrivCursor;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Procedure proc_up_dts_product_cat_dynsql failed due to '||SQLERRM);
END proc_up_dts_product_cat_dynsql;
/
The database hurls ORA-00920: invalid relational operator when we submit a SQL statement with a syntax error in a WHERE clause. Usually it's a typo. This is extremely easy to do in dynamic SQL, because we cannot see the whole statement except at run time.
You haven't posted the generated update statement. Well you can't, as your exception handling doesn't display it. Pro tip: when working with dynamic SQL always log or display the generated statement, in the exception block if nowhere else:
dbms_output.put_line('generated statement:'|| dynamicsql);
So this is just a guess but this line looks suspicious ...
when dateentered_op='between' then ' and TO_CHAR(dts_cm_dateentered,''YYYY-MM-DD'') between ' || dateentered
... because it appears to generate a BETWEEN statement with no AND clause. The BETWEEN operator requires two bounds.
But it could be many things. You may be running with an unusual combination of parameters which generates an invalid statement. You need better logging.

Execute immediate error in Oracle

I want to execute the following command through a cursor where I have column name and column values in a different table.
However the script fails with following error message.
ORA-00933: SQL command not properly ended
execute immediate 'UPDATE EMP_DETAILS_T SET ' || EMP_REC.COLUMN_NAME || ' = ' || '''' || EMP_REC.VALUE ||''' ' || ' where employee_id = ' || ''''|| EMP_REC.EMPLOYEE_ID || ''' ' ;
entire command is as follow.
DECLARE
CURSOR CR_EMP_ATT IS
SELECT COLUMN_NAME,
VALUE,
EMPLOYEE_ID
FROM UPDATE_DATA_T
WHERE EMPLOYEE_ID = P_EMP_ID;
BEGIN
FOR CR_EMP IN CR_EMP_ATT LOOP
BEGIN
EXECUTE IMMEDIATE 'Update EMP_DETAILS_T set ' || CR_EMP.COLUMN_NAME || ' = ' ||''''||CR_EMP.VALUE||''''|| ' where employee_id = ' ||''''|| P_EMP_ID||'''';
DBMS_OUTPUT.PUT_LINE('temp table updated');
END;
END LOOP;
END;
I have placed this query in a procedure to run when needed by employee.
Your value column includes values which contain a single quote. (The ampersand isn't going to be a problem here). You can see how that breaks the statement by displaying it before execution:
dbms_output.put_line('Update EMP_DETAILS_T set ' || CR_EMP.COLUMN_NAME
|| ' = ' ||''''||CR_EMP.VALUE||''''|| ' where employee_id = '
||''''|| P_EMP_ID||'''');
... which reveals:
Update EMP_DETAILS_T set SOME_COLUMN = 'Standard & Poor's' where employee_id = 'ABC123'
... which has unbalanced single quotes; you can even see that in the syntax highlighting.
The simplest fix is to use bind variables for the two values - you can't for the column name - and pass the actual values with the USING clause:
EXECUTE IMMEDIATE 'Update EMP_DETAILS_T set ' || CR_EMP.COLUMN_NAME
|| ' = :VALUE where employee_id = :EMP_ID'
USING CR_EMP.VALUE, P_EMP_ID;
Does your value CR_EMP.VALUE contain any ' character?
That would be another reason to use bind variables, i.e.
EXECUTE IMMEDIATE 'Update EMP_DETAILS_T set '||CR_EMP.COLUMN_NAME||' = ' :val WHERE employee_id = :id'
USING CR_EMP.VALUE, P_EMP_ID;

procedure issue(error in syntax)

I have the procedure block:
begin
for i in (select grantee
,table_name
,privilege
from user_tab_privs_made
where grantee='TEST')
loop
revoke i.privilege on i.table_name from i.grantee;
end loop;
end;
and the error occurs:
You need to issue the revoke as EXECUTE IMMEDIATE, building a dynamic string with the command you want to be executed:
execute immediate 'revoke ' || i.privilege || ' on ' || i.table_name
|| ' from ' || i.grantee;

Resources