oracle delete selected objects from schema - oracle

I want to delete objects from schema and I have stored all the objects those should not be deleted in a table, all other objects which are not in the table should be deleted. I have following code which is not working can some one help me here. I have searched the net there is only one thing "DELETE ALL OBJECT" which is not relevant to my case.
DECLARE
stringa VARCHAR2(100);
stringb VARCHAR2(1000) := '';
CURSOR cur IS
SELECT *
FROM user_objects;
BEGIN
FOR c IN cur LOOP
BEGIN
stringa := '';
BEGIN
SELECT tab_name
INTO stringb
FROM zretain_list;
IF c.object_type = 'VIEW' THEN
stringa := 'drop view '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'TABLE'
AND c.object_name != stringb THEN
stringa := 'drop table "'
|| c.object_name
|| '" cascade constraints';
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'SEQUENCE' THEN
stringa := 'drop sequence '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'PACKAGE' THEN
stringa := 'drop package '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'TRIGGER' THEN
stringa := 'drop trigger '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'PROCEDURE' THEN
stringa := 'drop procedure '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'FUNCTION' THEN
stringa := 'drop function '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'SYNONYM' THEN
stringa := 'drop synonym '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'INDEX' THEN
stringa := 'drop index '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'PACKAGE BODY' THEN
stringa := 'drop PACKAGE BODY '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
ELSIF c.object_type = 'DATABASE LINK' THEN
stringa := 'drop database link '
|| c.object_name;
EXECUTE IMMEDIATE stringa;
END IF;
EXCEPTION
WHEN OTHERS THEN
NULL;
-- PURGE recyclebin
END;
END;
END LOOP;
END;
/

You can start with something like
begin
For i in (select object_type, object_name from user_objects o
where object_name != 'ZRETAIN_LIST' and object_type in ('TABLE', 'FUNCTION', 'PROCEDURE', 'PACKAGE', 'SEQUENCE' )
and not exists ( select 1 from zretain_list where tab_name = o.object_name ) )
loop
execute immediate 'drop '||i.object_type || ' ' || i.object_name ;
end loop;
end;
/

Related

Oracle PLSQL invalid cursor error I don't understand

I'm still a relatively newbe when it comes to PL/SQL.
Using Oracle 12c on Linux RHEL 6.8, the following shell script will attempt to activate all RI constraints in a collection of tables, and if they fail with parent key failures, it will dump the first 100 rows (or less) of the offending data. Or at least that is the goal. Since the script deals mostly with system tables on 12c (with only a small user table list that is unique to my installation), I'm including the whole thing exactly from my environment.
The main work occurs in the exception handling where the system tables are queried for the constraint, and user queries are formed from those data.
As a extra goal, the output is rather messy and I want to clean it up, but first it has to work :)
The output / error I get for my tables is the following:
ERROR Handling here for table NRNG_MTC_VST Constraint Name:
SYS_C0011790 Final SQL = SELECT DISTINCT NRNG_MTC_VST.LOG_CRT_DT ,
NRNG_MTC_VST.NRRNG_MTC_LG_ID FROM ODB_PRIMARY.NRNG_MTC_VST WHERE NOT
EXISTS (SELECT 1 FROM ODB_PRIMARY.NRNG_MTC_LOG WHERE
NRNG_MTC_VST.LOG_CRT_DT = NRNG_MTC_LOG.LOG_CRT_DT AND
NRNG_MTC_VST.NRRNG_MTC_LG_ID = NRNG_MTC_LOG.NRRNG_MTC_LG_ID) FETCH
FIRST 100 rows only
---xxx End SQL DECLARE
* ERROR at line 1: ORA-01001: invalid cursor ORA-06512: at line 111 ORA-02298: cannot validate (ODB_PRIMARY.SYS_C0011790) - parent keys
not found
The output SQL from my print_line is correct, and would work if pasted directly into a SQLDeveloper session. There is just something silly about how the cursor is defined I don't understand.
The full text of the script. BYW, if you see other bonehead changes that should be made unrelated to the error, please suggest them as well.
cd $OGGHOME/scripts
export ORACLE_SID=odbod07 $ORACLE_HOME/bin/sqlplus <<-EOF / as sysdba
alter session set container=p01_odbod07;
set echo on set feedback on
set heading off
set serveroutput on size 10000
DECLARE finalsql varchar2(2048);
part1sql varchar2(1024) ;
part2sql varchar2(1024) := ' ';
cownername varchar2(1024);
ctablename varchar2(1024);
pownername varchar2(1024);
ptablename varchar2(1024);
cnt number := 0;
-- Weak cursor defs
my_cursor sys_refcursor;
BEGIN FOR i in (
select owner, table_name, constraint_name
from dba_constraints
where constraint_type = 'R'
and status = 'DISABLED'
and owner = 'ODB_PRIMARY'
and TABLE_NAME in
-- enter user tables with RI constraints here
('RRNG_MTC_STN_CPLY',
'NRNG_MTC_VST_MTRL_USG',
'NRNG_MTC_VST',
'CAR_CORE',
'NRNG_MTC_LOG'))
-- end user table definitions, rest of code should rely only on system tables
LOOP BEGIN
dbms_output.put_line('alter table '||i.owner|| '.' ||
i.table_name || ' enable constraint '||i.constraint_name);
execute immediate 'alter table '||i.owner|| '.' ||
i.table_name || ' enable constraint '||i.constraint_name;
EXCEPTION
-- exception handling - dump offending data
WHEN OTHERS THEN -- take all exceptions for now
dbms_output.put_line ('ERROR Handling here for table ' ||
i.table_name || ' Constraint Name: ' ||i.constraint_name);
finalsql := 'SELECT DISTINCT ';
part1sql := '';
part2sql := ' ';
cnt := 0;
for constraint in (
SELECT ucc1.OWNER as childowner,
ucc1.TABLE_NAME as childtable,
ucc1.column_name as childcolumn,
ucc2.OWNER as parentowner,
ucc2.TABLE_NAME as parenttable,
ucc2.column_name as parentcolumn,
utc1.data_type as childdatatype,
utc1.data_length as childdatalen
FROM all_constraints uc ,
all_cons_columns ucc1 ,
all_cons_columns ucc2,
all_tab_columns utc1
WHERE
uc.constraint_name = ucc1.constraint_name
AND uc.r_constraint_name = ucc2.constraint_name
AND ucc1.POSITION = ucc2.POSITION
AND ucc1.table_name = utc1.table_name
AND ucc1.column_name = utc1.column_name
AND uc.constraint_type = 'R'
AND uc.constraint_name = i.constraint_name
ORDER BY ucc1.TABLE_NAME , uc.constraint_name)
loop
cownername := constraint.childowner;
ctablename := constraint.childtable;
pownername := constraint.parentowner;
ptablename := constraint.parenttable;
if cnt > 0 then
part1sql := part1sql || ' , ';
part2sql := part2sql || ' AND ';
end if;
part1sql := part1sql || constraint.childtable ||
'.'||constraint.childcolumn || ' ';
part2sql := part2sql || constraint.childtable || '.'
|| constraint.childcolumn || ' = '
|| constraint.parenttable || '.' ||
constraint.parentcolumn;
cnt := cnt + 1;
end loop;
finalsql := finalsql || part1sql ||
' FROM ' || ' ' || cownername ||
'.' || ctablename ||
' WHERE NOT EXISTS (SELECT 1 FROM ' ||
pownername || '.' || ptablename ||
' WHERE ' || part2sql || ') FETCH FIRST 100 rows only';
dbms_output.put_line ('Final SQL = ' || finalsql);
dbms_output.put_line ('---xxx End SQL');
open my_cursor for finalsql;
dbms_sql.return_result(my_cursor);
close my_cursor;
-- EXECUTE IMMEDIATE finalsql;
END;
end loop; end;
/
EOF
Many thanks for any help provided.
Brian
Just to narrow this down to a simple test case, I think this is the error you are seeing:
declare
my_cursor sys_refcursor;
begin
open my_cursor for 'select ''Hello, world'' as message from dual';
dbms_sql.return_result(my_cursor);
close my_cursor; -- << Remove this line
end;
/
ERROR at line 1:
ORA-01001: invalid cursor
ORA-06512: at line 6
This is because you attempted to close the cursor when you have already passed it to dbms_sql for processing. Remove the line with close my_cursor.
declare
my_cursor sys_refcursor;
begin
open my_cursor for 'select ''Hello, world'' as message from dual';
dbms_sql.return_result(my_cursor);
end;
/
PL/SQL procedure successfully completed.
ResultSet #1
MESSAGE
------------
Hello, world
1 row selected.
I had same kind of issue when i tried to print Ref_cursor directly. Then i created a Record type variable and then fetched field values in that variable and then i used DBMS_OUTPUT for that record type variable.
Please see if below code and scenario can help you-
set serveroutput on;
declare
v_sql varchar2(1000);
v_cursor sys_refcursor;
type myrec is record(col1 varchar2(100),col2 varchar2(1000));
rec myrec;
begin
v_sql:='select name,status from t_employee where user_id in (''C001117'',''C001122'')';
open v_cursor for v_sql;
loop
fetch v_cursor
into rec;
exit when v_cursor%notfound;
dbms_output.put_line( rec.col1||':status '||rec.col2 );
end loop;
end;
/
The following is my semi-complete script. Given a table list, it will attempt to activate the RI Constraints, and if they fail it will print out the FK data records in the child table that prevent it from being applied.
The hardest part of this project was the fact that the FKs can be any number of columns and of any type, so the print the results of the select in this case was very tricky (IMO).
Thanks for the help people provided.
cd $OGGHOME/scripts
. ./functions.sh
$ORACLE_HOME/bin/sqlplus ${ORACLE_USERID}/${ORACLE_PASSWORD}#${ORACLE_SID} << EOF
set echo on
set feedback on
set heading off
set serveroutput on size unlimit
DECLARE
finalsql varchar2(2048);
part1sql varchar2(1024) ;
part2sql varchar2(1024) := ' ';
cownername varchar2(1024);
ctablename varchar2(1024);
pownername varchar2(1024);
ptablename varchar2(1024);
cnt number := 0;
desc_tab dbms_sql.desc_tab;
col_count INTEGER;
cursor_name INTEGER;
-- Weak cursor defs
my_cursor sys_refcursor;
col1 varchar2(50);
d number;
j number;
lineout varchar2(2048);
plineout varchar2(2048);
rows number;
eCount number := 0;
BEGIN
FOR i in (
select owner, table_name, constraint_name
from dba_constraints
where constraint_type = 'R'
and status = 'DISABLED'
and owner = '$DBSCHEMA'
and TABLE_NAME in (
'RRNG_MTC_STN_CPLY',
'NRNG_MTC_VST_MTRL_USG',
'NRNG_MTC_VST',
'MTC_TSK_HRHY'))
LOOP
BEGIN
dbms_output.put_line ('.');
dbms_output.put_line ('=====================================');
dbms_output.put('alter table '||i.owner|| '.' || i.table_name || ' enable constraint '||i.constraint_name);
execute immediate 'alter table '||i.owner|| '.' || i.table_name || ' enable constraint '||i.constraint_name;
dbms_output.put_line (' ... SUCCESS');
EXCEPTION -- exception handling - dump offending data
WHEN OTHERS THEN
eCount := eCount + 1;
dbms_output.put_line (' ... FAILED. Constraint Name: ' || i.constraint_name);
finalsql := 'SELECT DISTINCT ';
part1sql := '';
part2sql := ' ';
cnt := 0;
for constraint in (
SELECT ucc1.OWNER as childowner,
ucc1.TABLE_NAME as childtable,
ucc1.column_name as childcolumn,
ucc2.OWNER as parentowner,
ucc2.TABLE_NAME as parenttable,
ucc2.column_name as parentcolumn,
utc1.data_type as childdatatype,
utc1.data_length as childdatalen
FROM all_constraints uc ,
all_cons_columns ucc1 ,
all_cons_columns ucc2,
all_tab_columns utc1
WHERE
uc.constraint_name = ucc1.constraint_name
AND uc.r_constraint_name = ucc2.constraint_name
AND ucc1.POSITION = ucc2.POSITION
AND ucc1.table_name = utc1.table_name
AND ucc1.column_name = utc1.column_name
AND uc.constraint_type = 'R'
AND uc.constraint_name = i.constraint_name
ORDER BY ucc1.TABLE_NAME ,
uc.constraint_name)
loop
cownername := constraint.childowner;
ctablename := constraint.childtable;
pownername := constraint.parentowner;
ptablename := constraint.parenttable;
if cnt > 0 then
part1sql := part1sql || ' , ';
part2sql := part2sql || ' AND ';
end if;
part1sql := part1sql || constraint.childtable || '.' || constraint.childcolumn || ' ';
part2sql := part2sql || constraint.childtable || '.' || constraint.childcolumn || ' = '
|| constraint.parenttable || '.' || constraint.parentcolumn;
cnt := cnt + 1;
end loop;
finalsql := finalsql || part1sql || ' FROM ' || ' ' || cownername || '.' || ctablename || ' WHERE NOT EXISTS (SELECT 1 FROM ' ||
pownername || '.' || ptablename || ' WHERE ' || part2sql || ') FETCH FIRST 100 rows only';
dbms_output.put_line ('Final SQL = (' || finalsql || ')');
-- dbms_output.put_line ('---xxx End SQL');
lineout := 'Child Table: ' || ctablename || '(';
plineout := 'Parent Table: ' || ptablename;
cursor_name := dbms_sql.open_cursor;
dbms_sql.PARSE (cursor_name, finalsql, DBMS_SQL.NATIVE);
d := dbms_sql.execute (cursor_name);
dbms_sql.describe_columns (cursor_name, col_count, desc_tab);
for j in 1..col_count
LOOP
DBMS_SQL.DEFINE_COLUMN (cursor_name, j, col1, 30);
lineout := lineout || desc_tab(j).col_name || ' , ';
-- plineout := plineout || constraint.parentcolumn || ' ';
-- dbms_output.put_line ('Column 1: ' || j || ' is ' || desc_tab(j).col_name || ' type '
-- || desc_tab(j).col_type);
END LOOP j;
lineout := lineout || ')';
-- plineout := plineout || ')';
dbms_output.put_line (lineout);
dbms_output.put_line (plineout);
lineout := NULL;
for j in 1..col_count
LOOP
if j > 1 then
lineout := lineout || ' ';
end if;
lineout := lineout || desc_tab(j).col_name;
END LOOP;
dbms_output.put_line (lineout);
dbms_output.put_line ('----------------------------------------');
LOOP
rows := dbms_sql.fetch_rows (cursor_name);
EXIT WHEN rows = 0;
lineout := NULL;
for j in 1..col_count
LOOP
dbms_sql.column_value (cursor_name, j, col1);
if j > 1 then
lineout := ltrim(lineout || ' ' || col1);
else
lineout := col1;
END IF;
END LOOP;
dbms_output.put_line (lineout);
END LOOP;
dbms_sql.close_cursor (cursor_name);
END;
end loop;
end;
/
EOF
your FETCH FIRST 100 rows only would seem to be out of place.
This is part of the BULK COLLECT clause in a SELECT statement in PL/SQL; as far as I know, it is not part of a SQL statement you can pass into a cursor like this
This is resulting in the cursor statement being invalid

Gettig error PLS-00364

I'm trying to create a stored procedure where I'm passing select statement to for loop and i'm using dynamic table which is passing at runtime and getting below error:
LINE 23 PLS-00364: loop index variable 'I' use is invalid
LINE 19 PL/SQL: ORA-00942: table or view does not exist
CREATE OR REPLACE PROCEDURE CREATE_TEST(TBL_NM IN VARCHAR2)
IS
SRC_ID NUMBER(38);
SQL_Q VARCHAR2(250);
DEL_F VARCHAR2(250);
BEGIN
FOR I in (SELECT DEL_IND FROM TBL_NM)
LOOP
SRC_ID := SRC_FILE_ID_SEQ.NEXTVAL;
IF I.DEL_IND = 0
THEN
execute immediate 'INSERT INTO TEST_HIST ' || ' (a,b,c,d,e,DEL_IND) ' ||
' SELECT a,b,c,d,e, '|| 0 || ' || ' FROM ' || TBL_NM;
ELSIF I.DEL_IND = 1
THEN
execute immediate 'INSERT INTO JESTX_IGNR ' || ' (a,b,c,d,e,DEL_IND,SRC_ID_NO) ' ||
' SELECT a,b,c,d,e, '|| 2 ||' , '|| SRC_ID || ' FROM ' || TBL_NM;
END IF ;
END LOOP;
COMMIT;
END;
I call the procedure using:
EXEC CREATE_TEST('abc');
What you want is a REF CURSOR as you cannot use cursor for loop with dynamic sql.
I dont know the exact datatype for your column DEL_IND. Please declare accordingly.
Here is some more information on Oracle REF CURSORS.
Try below
CREATE OR REPLACE PROCEDURE CREATE_TEST(TBL_NM IN VARCHAR2)
IS
TYPE c1ref is REF CURSOR;
SRC_ID NUMBER(38);
SQL_Q VARCHAR2(250);
DEL_F VARCHAR2(250);
DEL_IND NUMBER(5);
BEGIN
vsql_text := 'select DEL_IND from ' || TBL_NM;
open c1ref for vsql_text;
LOOP
SRC_ID := SRC_FILE_ID_SEQ.NEXTVAL;
fetch c1ref into DEL_IND;
exit when c1ref%NOTFOUND;
IF (DEL_IND = 0)
THEN
execute immediate 'INSERT INTO TEST_HIST ' || ' (a,b,c,d,e,DEL_IND) ' ||
' SELECT a,b,c,d,e, '|| 0 || ' || FROM ' || TBL_NM;
ELSIF (DEL_IND = 1)
THEN
execute immediate 'INSERT INTO JESTX_IGNR ' || ' (a,b,c,d,e,DEL_IND) ' ||
' SELECT a,b,c,d,e, '|| 2 ||' , '|| SRC_ID || ' FROM ' || TBL_NM;
END IF ;
END LOOP;
CLOSE c1ref;
COMMIT;
END;

Delete all objects in schema using batch file in Oracle

I have below Select query which will generate delete statements to delete all objects in schema.
select 'DROP '||OBJECT_TYPE||' '||OWNER||'.'||OBJECT_NAME
|| case when OBJECT_TYPE = 'TABLE'
then ' CASCADE CONSTRAINTS PURGE' else '' end
||';'
from all_objects
where OWNER = 'RATOR_MONITORING';
I want to create batch file and suppose that instead of generating delete statements separetly I can create may be cursor or something and save it in batch file and run the batch file to delete all contents in schema. How to do it?
You can find many script in the Internet. Neither of them work on 100%. There can we various gotchas. Like scheduler chains or materialized view groups.
This is the one I use (it is also inspired by one I found in the Internet)
set serveroutput on size unlimited
declare
v_ItemCount integer;
begin
SELECT count(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
while (v_ItemCount > 0) loop
for v_Cmd in (SELECT 'drop ' || AO.OBJECT_TYPE || ' ' || '"'||AO.OWNER||'"'|| '.' || '"'||AO.OBJECT_NAME||'"' ||
DECODE(AO.OBJECT_TYPE,
'TABLE',
' CASCADE CONSTRAINTS',
'') as DROPCMD,
AO.OWNER,
AO.OBJECT_TYPE,
AO.OBJECT_NAME
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%')
loop
begin
if v_Cmd.OBJECT_TYPE = 'SCHEDULE' then
DBMS_SCHEDULER.DROP_SCHEDULE(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'JOB' then
DBMS_SCHEDULER.DROP_JOB(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'PROGRAM' then
DBMS_SCHEDULER.DROP_PROGRAM(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
else
execute immediate v_Cmd.dropcmd;
end if;
dbms_output.put_line(v_Cmd.dropcmd);
exception
when others then
null; -- ignore errors
end;
end loop;
SELECT count(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX','LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
end loop;
execute immediate 'purge dba_recyclebin';
end;
Here is the script
begin
for i in (select * from dba_objects where owner = 'SO' and object_type <> 'TABLE')
loop
execute immediate 'drop ' || i.object_type || ' ' || i.object_name;
end loop;
for j in (select * from dba_objects where owner = 'SO' and object_type = 'TABLE')
loop
execute immediate 'drop ' || j.object_type || ' ' || j.object_name || ' cascade constraints';
end loop;
end;
/
This link provides details about how to create shell script or batch script to run sql scripts.
https://oracle-base.com/articles/misc/oracle-shell-scripting
Here we go i have compiled a shell to perform the Purge Schema. Let me know if this helps.
#weekly report
#!/bin/ksh
export ORACLE_HOME=/opt/oracle/product/1020
export PATH=$ORACLE_HOME/bin:$PATH:.
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
ABC=`sqlplus -s <username>/<password>#<sid> <<+
set sqlbl on;
set serveroutput on;
DECLARE
v_ItemCount INTEGER;
BEGIN
SELECT COUNT(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
WHILE (v_ItemCount > 0)
LOOP
FOR v_Cmd IN
(SELECT 'drop '
|| AO.OBJECT_TYPE
|| ' '
|| '"'
||AO.OWNER
||'"'
|| '.'
|| '"'
||AO.OBJECT_NAME
||'"'
|| DECODE(AO.OBJECT_TYPE, 'TABLE', ' CASCADE CONSTRAINTS', '') AS DROPCMD,
AO.OWNER,
AO.OBJECT_TYPE,
AO.OBJECT_NAME
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%'
)
LOOP
BEGIN
IF v_Cmd.OBJECT_TYPE = 'SCHEDULE' THEN
DBMS_SCHEDULER.DROP_SCHEDULE(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'JOB' THEN
DBMS_SCHEDULER.DROP_JOB(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'PROGRAM' THEN
DBMS_SCHEDULER.DROP_PROGRAM(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSE
EXECUTE immediate v_Cmd.dropcmd;
END IF;
dbms_output.put_line(v_Cmd.dropcmd);
EXCEPTION
WHEN OTHERS THEN
NULL; -- ignore errors
END;
END LOOP;
SELECT COUNT(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX','LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
END LOOP;
EXECUTE immediate 'purge dba_recyclebin';
END;
/
exit
+`

Spool the data from execute immediate within pl/sql block

Ho to spool the data from execute immediate in pl/sql.
Below is the code.
DECLARE
from_dt varchar(300):=&from_date;
to_dt varchar2(300):=&to_date;
account varchar2(200):=&account;
mbl_table varchar2(100);
dn_table varchar2(100);
id number;
Begin
select aid into id from account where upper(acode)=upper(account);
select tablename into mbl_table from partner_mbl where pid in (select pid from account where upper(acode)=upper(account));
select dn_tablename into dn_table from partner_mbl where pid in (select pid from account where upper(acode)=upper(account));
dbms_output.put_line(mbl_table);
FOR i IN (select 'p_'||to_char((ROWNUM-1 + to_date(from_dt, 'ddmonyyyy')),'ddmonyyyy') part FROM all_objects
WHERE ROWNUM-2 < to_date(to_dt, 'ddmonyyyy')-to_date(from_dt, 'ddmonyyyy'))loop
execute immediate 'Select a.pcode,A.Acode,To_Char(A.Mobile),a.msg,a.senderid,To_Char(A.Rts,'||'''dd/mm/yyyy hh24:mi:ss'''||'),To_Char(A.Sts,'||'''dd/mm/yyyy hh24:mi:ss'''||'),A.Statusflag,A.Statusid,To_Char(B.Lastts,'||'''dd/mm/yyyy hh24:mi:ss'''||'),B.Statusflag,B.Err_Des From '|| mbl_table ||' partition('||i.part||') A, '|| dn_table ||' partition('||i.part||') B Where a.aid='||id|| ' And A.Msgid = B.Msgid(+)';
end loop;
End;
how to spool the output of execute immediate into csv file
DECLARE
from_dt varchar(300) := &from_date;
to_dt varchar2(300) := &to_date;
account varchar2(200) := &account;
mbl_table varchar2(100);
dn_table varchar2(100);
id number;
/*define types*/
/* change the next varchar2(1000) with your types*/
t_pcode IS TABLE OF varchar2(1000);
v_pcode t_pcode;
t_Acode IS TABLE OF varchar2(1000);
v_Acode t_Acode;
t_Mobile IS TABLE OF varchar2(1000);
v_Mobile t_Mobile;
t_msg IS TABLE OF varchar2(1000);
v_msg t_msg;
t_senderid IS TABLE OF varchar2(1000);
v_senderid t_senderid;
t_Rts IS TABLE OF varchar2(1000);
v_Rts t_Rts;
t_Sts IS TABLE OF varchar2(1000);
V_Sts t_Sts;
t_Statusflag IS TABLE OF varchar2(1000);
v_Statusflag t_Statusflag;
t_Statusid IS TABLE OF varchar2(1000);
v_Statusid t_Statusid;
t_Lastts IS TABLE OF varchar2(1000);
v_Lastts t_Lastts;
t_Statusflag IS TABLE OF varchar2(1000);
v_Statusflag t_Statusflag;
t_Err_Des IS TABLE OF varchar2(1000);
v_Err_Des t_Err_Des;
/*end types*/
Begin
select aid into id from account where upper(acode) = upper(account);
select tablename
into mbl_table
from partner_mbl
where pid in
(select pid from account where upper(acode) = upper(account));
select dn_tablename
into dn_table
from partner_mbl
where pid in
(select pid from account where upper(acode) = upper(account));
dbms_output.put_line(mbl_table);
FOR i IN (select 'p_' ||
to_char((ROWNUM - 1 + to_date(from_dt, 'ddmonyyyy')),
'ddmonyyyy') part
FROM all_objects
WHERE ROWNUM - 2 < to_date(to_dt, 'ddmonyyyy') -
to_date(from_dt, 'ddmonyyyy')) loop
/* execute immediate 'Select a.pcode,A.Acode,To_Char(A.Mobile),a.msg,a.senderid,To_Char(A.Rts,' ||
'''dd/mm/yyyy hh24:mi:ss''' || '),To_Char(A.Sts,' ||
'''dd/mm/yyyy hh24:mi:ss''' ||
'),A.Statusflag,A.Statusid,To_Char(B.Lastts,' ||
'''dd/mm/yyyy hh24:mi:ss''' ||
'),B.Statusflag,B.Err_Des From ' || mbl_table ||
' partition(' || i.part || ') A, ' || dn_table ||
' partition(' || i.part || ') B Where a.aid=' || id ||
' And A.Msgid = B.Msgid(+)' ;
*/
execute immediate 'Select a.pcode,A.Acode,To_Char(A.Mobile),a.msg,a.senderid,To_Char(A.Rts,' ||
'''dd/mm/yyyy hh24:mi:ss''' || '),To_Char(A.Sts,' ||
'''dd/mm/yyyy hh24:mi:ss''' ||
'),A.Statusflag,A.Statusid,To_Char(B.Lastts,' ||
'''dd/mm/yyyy hh24:mi:ss''' ||
'),B.Statusflag,B.Err_Des From ' || mbl_table ||
' partition(' || i.part || ') A, ' || dn_table ||
' partition(' || i.part || ') B Where a.aid=' || id ||
' And A.Msgid = B.Msgid(+)'
BULK COLLECT INTO v_pcode, v_Acode, v_Mobile, v_msg, v_senderid,
v_Rts, V_Sts, v_Statusflag, v_Statusid, v_Lastts,
v_Statusflag, v_Err_Des;
for i.. v_pcode.count loop
dbms_output.put_line('pcode and msg values are: '||v_pcode(i)||' ' ||v_msg(i) ||' at line' || i );
/*you can get out other values with same way*/
end loop;
End;
you can also take a look at oracle documentation for "oracle collections", "execute immediate", "bulk collect".
my previous post could solve your problem however here is a simple example as additional info.
DECLARE
TYPE emp_typ IS TABLE OF scott.emp%ROWTYPE;
e_tab emp_typ;
BEGIN
EXECUTE IMMEDIATE 'SELECT * FROM emp'
BULK COLLECT INTO e_tab;
DBMS_OUTPUT.put_line('Dynamic EXECUTE: ' || e_tab.count);
for i in 1..e_tab.count loop
DBMS_OUTPUT.put_line( e_tab(i).ename ||':'|| e_tab(i).empno );
null;
end loop;
END;
/

Oracle: Search an entire DB for a string: Error ORA-00911

I have created the PL/SQL stored procedure below to search an entire Oracle11g database for a string (srchstr) and return the table and column where that string was found to a table called VALUESEARCHRESULTS.
The procedure has ran successfully in Oracle XE via SQL Developer as a user. However, when try to run it as user SYS in Oracle11g for schema ABC, I receive the following error:
ORA-00911: invalid character
Cause: identifiers may not start with any ASCII character other than letters and numbers. $#_ are also allowed after the first character. Identifiers enclosed by double quotes may contain any character other than a double quote. Alternative quotes (q"#...#") cannot use spaces, tabs, or carriage returns as delimiters. For all other contexts, consult the SQL Language Reference Manual.
Does anyone know why this may be? Please see my code below.
CREATE OR REPLACE PROCEDURE ABC.FIND_STRING(p_str IN VARCHAR2) authid current_user is
l_query clob;
srchstr varchar2(30) := '';
r_cname varchar2(30) := '';
l_case clob;
l_runquery boolean;
l_tname varchar2(30);
l_cname varchar2(30);
begin
dbms_application_info.set_client_info( '%' || upper(p_str) || '%' );
for x in (select * from user_tables)
loop
l_query := 'select ''' || x.table_name || ''', $$
from ' || x.table_name || '
where rownum = 1 and ( 1=0 ';
l_case := 'case ';
l_runquery := FALSE;
for y in ( select *
from user_tab_columns
where table_name = x.table_name
and (data_type in('CHAR', 'DATE', 'FLOAT', 'NCHAR', 'NUMBER', 'NVARCHAR2', 'VARCHAR2' )
or data_type like 'INTERVAL%' or data_type like 'TIMESTAMP%' )
)
loop
l_runquery := TRUE;
l_query := l_query || ' or upper(' || y.column_name ||
') like userenv(''client_info'') ';
l_case := l_case || ' when upper(' || y.column_name ||
') like userenv(''client_info'') then ''' ||
y.column_name || '''';
end loop;
if ( l_runquery )
then
l_case := l_case || ' else NULL end';
l_query := replace( l_query, '$$', l_case ) || ')';
begin
execute immediate l_query into l_tname, l_cname;
r_cname := l_cname;
dbms_application_info.read_client_info(srchstr);
insert into ABC.ValueSearchResults (resulttable, resultcolumn, searchstring) values (x.table_name, r_cname, srchstr);
dbms_output.put_line
( srchstr || ' found in ' || l_tname || '.' || l_cname );
exception
when no_data_found then
dbms_output.put_line
( srchstr || ' has no hits in ' || x.table_name );
end;
end if;
end loop;
end;
EDIT: The stored procedure above compiles without error. The code below executes the stored procedure by passing values from a table into the stored procedure. The error shows when the code below is ran:
BEGIN
FOR c IN (SELECT ControlValue FROM ABC.ControlValues) LOOP
ABC.FIND_STRING(c.ControlValue);
END LOOP;
END;
I have found a resolution for the issue I initially raised.
Cause of error: Not specifying a schema; only grabbing user-specific tables.
While the stored procedure would execute when deployed as user ABC, the error generated when running the stored procedure as a user other ABC. It appeared the same table name existed in multiple schemas. Thus, adding an OWNER variable specified the schema associated with the table name and eliminated the error.
Additionally, the procedure was originally searching for USER_TABLES. This limited the results to only the tables of the current schema. By replacing USER_TABLES with DBA_TABLES, the stored procedure's search spanned through all tables of the database.
See below for the corrected code:
CREATE OR REPLACE
PROCEDURE FIND_STRING(
p_str IN VARCHAR2) authid current_user
IS
l_query CLOB;
srchstr VARCHAR2(100) := '';
r_cname VARCHAR2(100) := '';
l_case CLOB;
l_runquery BOOLEAN;
l_tname VARCHAR2(100);
l_cname VARCHAR2(100);
BEGIN
dbms_application_info.set_client_info( '%' || upper(p_str) || '%' );
FOR x IN
(SELECT *
FROM dba_tables
WHERE table_name <> 'CONTROLVALUES'
AND table_name <> 'VALUESEARCHRESULTS'
AND tablespace_name <> 'SYSTEM'
AND tablespace_name <> 'SYSAUX'
AND tablespace_name <> 'TEMP'
AND tablespace_name <> 'UNDOTBS1'
)
LOOP
l_query := 'select ''' || x.owner || '.' || x.table_name || ''', $$
from ' || x.owner || '.' || x.table_name || '
where rownum = 1 and ( 1=0 ';
l_case := 'case ';
l_runquery := FALSE;
FOR y IN
(SELECT *
FROM dba_tab_columns
WHERE table_name = x.table_name
AND owner = x.owner
AND (data_type IN ( 'CHAR', 'DATE', 'FLOAT', 'NCHAR', 'NUMBER', 'NVARCHAR2', 'VARCHAR2' )
OR data_type LIKE 'INTERVAL%'
OR data_type LIKE 'TIMESTAMP%' )
)
LOOP
l_runquery := TRUE;
l_query := l_query || ' or upper(' || y.column_name || ') like userenv (''client_info'') ';
l_case := l_case || ' when upper(' || y.column_name || ') like userenv (''client_info'') then ''' || y.column_name || '''';
END LOOP;
IF ( l_runquery ) THEN
l_case := l_case || ' else NULL end';
l_query := REPLACE( l_query, '$$', l_case ) || ')';
BEGIN
EXECUTE immediate l_query INTO l_tname, l_cname;
r_cname := l_cname;
dbms_application_info.read_client_info(srchstr);
INSERT
INTO VALUESEARCHRESULTS
(
resulttable,
resultcolumn,
searchstring
)
VALUES
(
x.table_name,
r_cname,
srchstr
);
dbms_output.put_line ( srchstr || ' found in ' || l_tname || '.' || l_cname );
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line ( srchstr || ' has no hits in ' || x.owner || '.' || x.table_name );
END;
END IF;
END LOOP;
END;

Resources