Truncate and drop storage in multiple tables in oracle - oracle

I wanna action a truncate and drop storage in multiple tables in oracle.
I am using the pl/SQL below :
BEGIN
FOR i IN (select('LOG_'||X.TABLE_ID) AS LogTables from LOGFILE X)
LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || i.LogTables ;
END LOOP;
END;
My code works perfectly but i wanna add the 'DROP STORAGE' clause.
How shall i Proceed ?

I found the answer :
BEGIN
FOR i IN (select('SDE_LOGPOOL_'||X.TABLE_ID) AS LogPoolTables from SDE_LOGFILE_POOL X)
LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || i.LogPoolTables || ' DROP STORAGE' ;
END LOOP;
END;

Related

oracle execute immediate command concatenation

oracle execute immediate command concatenation. e.g.
BEGIN EXECUTE IMMEDIATE 'DROP TABLE Foo'; END;
works.
BEGIN EXECUTE IMMEDIATE '''DROP TABLE ' || tableName || ''''; END;
BEGIN EXECUTE IMMEDIATE '''DROP TABLE ' || 'Foo'''; END;
not working.
Table name is an input parameter in stored procedure.
Your single quotes are improper.
Use following:
BEGIN EXECUTE IMMEDIATE 'DROP TABLE ' || tableName; END;
BEGIN EXECUTE IMMEDIATE 'DROP TABLE ' || 'Foo'; END;
Cheers!!

how to provide multiple bind variable for execute immediate inside pl/sql block

I have a table which contains the metadata of the table. The task is to periodically delete a specific set of tables, provided the information for where condition and how many days the data is retained are present.If a user needs to delete a data on daily basis, he simply enter his table name in audit log. The procedure will do the rest. The example is shown below.
Table structure:
CREATE TABLE delete_tbl_list (
id NUMBER NOT NULL,
table_name VARCHAR2(100) NOT NULL,
column_name VARCHAR2(100) NOT NULL,
day_retented NUMBER NOT NULL,
where_clause VARCHAR2(2000)
);
the day_retended is the number which will tell on how many days the data can hold.
select * from delete_tbl_list
ID TABLE_NAME COLUMN_NAME DAY_RETENTED WHERE_CLAUSE
---------- -----------------------------------------------
1 audit_log log_TS 60
So if i need to delete a table taking log_ts(timestamp) as column with 60days period as retention. The table in query needs to do
delete * from audit_log where log_ts<systimestamp -60
Now i need to do it using bulk delete and more dynamic and hence i wrote the procedure below,
create procedure dynamic_mass_delete as
TYPE tbl_rec_rowid IS TABLE OF ROWID INDEX BY PLS_INTEGER;
lv_del_exec_rec tbl_rec_rowid;
v_limit PLS_INTEGER := 10000;
m_date date:=sysdate;
total_records_deleted number:=0;
l_where delete_tbl_list.where_clause%type;
l_sql varchar2(2000);
TYPE ref_cur_type IS REF CURSOR;
delete_content ref_cur_type;
BEGIN
for i in (select table_name,COLUMN_NAME,DAY_RETENTED,WHERE_CLAUSE from delete_tbl_list) loop
DBMS_OUTPUT.PUT_LINE('tablename..'||i.table_name);
l_where:='';
m_date:=m_date-i.day_retented;
if i.where_clause is not null then
l_where:=' and '||i.where_clause;
end if;
OPEN delete_content FOR 'SELECT rowid from ' || i.table_name ||' where '|| i.COLUMN_NAME || ' <= to_timestamp('''||m_date||''')'||l_where;
LOOP
total_records_deleted := 0;
FETCH delete_content BULK COLLECT INTO lv_del_exec_rec LIMIT v_limit;
FORALL j IN lv_del_exec_rec.first..lv_del_exec_rec.last
execute immediate 'DELETE FROM :1 where rowid=:2 'using i.table_name,lv_del_exec_rec(j);
total_records_deleted := total_records_deleted + SQL%rowcount;
DBMS_OUTPUT.PUT_LINE('Delete count..'||total_records_deleted);
EXIT WHEN delete_content%notfound;
END LOOP;
CLOSE delete_content;
end loop;
EXCEPTION
when others then
DBMS_OUTPUT.PUT_LINE('Error-->'||SQLERRM);
END;
/
Now i getting error in the delete query stating invalid table name, i was not able to write dbms_output inside for all statment. Is it possible to use multiple bind variable inside a pl/sql procedure.
The error which i get is ,
Error-->ORA-00942: table or view does not exist
PL/SQL procedure successfully completed.
The table very much exists, but it is throwing error, i was not able to print inside the forall block too.
Switch to
execute immediate 'DELETE FROM ' || i.table_name ||' where rowid = ' || lv_del_exec_rec(j);
You can simplify your code as follows:
BEGIN
FOR TBL_DETAILS IN (
SELECT
TABLE_NAME,
COLUMN_NAME,
DAY_RETENTED,
WHERE_CLAUSE
FROM
DELETE_TBL_LIST
) LOOP
DBMS_OUTPUT.PUT_LINE('tablename..' || TBL_DETAILS.TABLE_NAME);
EXECUTE IMMEDIATE 'DELETE FROM '
|| TBL_DETAILS.TABLE_NAME
|| ' WHERE '
|| TBL_DETAILS.COLUMN_NAME
|| ' < SYSTIMESTAMP - '
|| TBL_DETAILS.DAY_RETENTED
|| CASE
WHEN TBL_DETAILS.WHERE_CLAUSE IS NOT NULL THEN ' AND ' || TBL_DETAILS.WHERE_CLAUSE
END;
DBMS_OUTPUT.PUT_LINE('Delete count..' || SQL%ROWCOUNT);
END LOOP;
END;
/
Hope, This will help you in creating simpler code.
Cheers!!

Create a table with oracle pl/sql

I get this error ORA-00933: SQL command not properly ended, but I cannot see what the problem is.
Creates the package:
CREATE OR REPLACE PACKAGE "TOOL_PKG" IS
PROCEDURE CREATE_ZTEMP_CLAIMS_TABLES;
END TOOL_PKG;
/
Create a procedure for the package. I get the error trying to run the procedure.
What I want to do is create a new table with an existing table. I need it dynamic because I'll be adding a lot more tables to the list.
CREATE OR REPLACE PACKAGE BODY CUBS_OWNER."TOOL_PKG" IS
PROCEDURE CREATE_NEW_TABLE IS
type array_t is table of varchar2(50) index by pls_integer;
my_table_t array_t;
elem varchar2(50);
c int;
BEGIN
my_table_t (1) := 'MY_TABLE';
elem := my_table_t.first;
while elem is not null loop
select count(*) into c from user_tables where table_name = upper('ZTEST_'||my_table_t(elem));
if c=0 then
Begin
execute immediate 'CREATE TABLE upper(NEWX_'||my_table_t(elem)||') AS SELECT * FROM upper('||my_table_t(elem)||') where rownum=0';
COMMIT;
DBMS_OUTPUT.put_line ('ZTEST_'||my_table_t(elem)||' created.');
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'tool_pkg.create_new_table...failed creating table '
|| CHR (10)
|| SQLERRM);
END;
end if;
elem := my_table_t.next(elem);
end loop;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'tool_pkg.create_new_table...failed creating table '
|| CHR (10)
|| SQLERRM);
END;
END tool_pkg;
/
I had to make sure the methods upper were outside the quotes.
Instead of this
execute immediate 'CREATE TABLE upper(NEWX_'||my_table_t(elem)||') AS SELECT * FROM upper('||my_table_t(elem)||') where rownum=0';
It had to be in this form
execute immediate 'CREATE TABLE '||upper('NEWX_'||my_table_t(elem))||' AS SELECT * FROM '||upper(my_table_t(elem))||' where rownum=0';

temporary storage in Oracle?

I need to store output of a query(which returns multiple rows) temporarily in Oracle. One of the ways to do this is using temporary table and I am using that currently. But the problem with them is that they stay around and cannot be created and dropped in a procedure willy nilly. Is there another object that I can use to temporarily store the output of a query to be able to use in the stored procedure ?
Here is my stored procedure for reference:
create or replace PROCEDURE procPrintOutput
IS
l_stmt VARCHAR2(512) := '';
create_table_stmt VARCHAR2(512) := 'create GLOBAL TEMPORARY TABLE temp(matViewLogQuery CLOB) ON COMMIT DELETE ROWS';
drop_mat_view_logs_stmt VARCHAR2(100) := 'DROP MATERIALIZED VIEW LOG ON ';
drop_temp_table VARCHAR2(512) := 'DROP TABLE temp';
ref_cursor SYS_REFCURSOR;
BEGIN
EXECUTE IMMEDIATE(create_table_stmt);
DBMS_OUTPUT.PUT_LINE('created temp table');
DECLARE
CURSOR LIST_OF_MVL IS SELECT * FROM USER_MVIEW_LOGS;
CURSOR CREATE_MVL IS SELECT * FROM temp;
BEGIN
FOR TEST IN LIST_OF_MVL
LOOP
BEGIN
DBMS_OUTPUT.PUT_LINE('owner : ' || TEST.OWNER || ' - name : ' || TEST.MASTER);
l_stmt := 'insert into temp SELECT SYS.DBMS_METADATA.get_dependent_ddl (''MATERIALIZED_VIEW_LOG'', '''||TEST.MASTER||''', '''||TEST.LOG_OWNER||''') from dual';
EXECUTE IMMEDIATE (l_stmt);
EXECUTE IMMEDIATE (drop_mat_view_logs_stmt || TEST.MASTER);
DBMS_OUTPUT.PUT_LINE('view dropped ... ');
END;
END LOOP;
FOR CREATE_SCRIPT IN CREATE_MVL
LOOP
BEGIN
DBMS_OUTPUT.PUT_LINE('SCRIPT : ' || CREATE_SCRIPT.matViewLogQuery);
EXECUTE IMMEDIATE(CREATE_SCRIPT.matViewLogQuery);
DBMS_OUTPUT.PUT_LINE('view recreated ... ');
END;
END LOOP;
END;
EXECUTE IMMEDIATE(drop_temp_table);
DBMS_OUTPUT.PUT_LINE('Done! Table dropped');
ROLLBACK;
END;
Thanks
instead of of temp table you can use collection in pl/sql and store all information that you need into the collection by BULK COLLECT
here small example
in my example I collect all DDLs for matviews and name of the views, then in simple cycle we can do any operations...
DECLARE
TYPE tDDL IS record (name varchar2(30), ddl CLOB);
TYPE tblDDL IS TABLE OF tDDL INDEX BY PLS_INTEGER;
l_ddls tblDDL;
BEGIN
SELECT object_name, dbms_metadata.get_ddl('MATERIALIZED_VIEW', object_name)
BULK COLLECT INTO l_ddls
from user_objects
where object_type= 'MATERIALIZED VIEW';
FOR indx IN 1 .. l_ddls.COUNT
LOOP
--do what you need with collected DDLs
DBMS_OUTPUT.PUT_LINE('view dropped ... ');
--your complex execute immediate logic here
dbms_output.put(l_ddls(indx).name);
dbms_output.put(' : ');
dbms_output.put_line(substr(l_ddls(indx).ddl, 100));
DBMS_OUTPUT.PUT_LINE('view recreated ... ');
END LOOP;
END;

PL/SQL - Execute immediate loop using parameter and if/then statement

Within a shell script I am using a pl/sql block to drop certain users using $USER parameter. If another parameter ${DROP_AB} is Y then drop all users from the cursor. How do I drop all users except one specific user ${USER}AB if the parameter passed is N? Please see below and help with suggestions:
BEGIN
DECLARE
CURSOR c1 IS
SELECT username FROM dba_users WHERE username LIKE '${USER}%';
BEGIN
FOR user_rec IN c1
IF ${DROP_AB}='Y' THEN
LOOP
EXECUTE IMMEDIATE 'DROP USER ' ||user_rec.username|| ' CASCADE';
ELSIF ${DROP_AB}='N' THEN
LOOP
--DROP ALL USERS EXCEPT FOR USER '${USER}AB'
END LOOP;
END;
END;
/
Untested code but somthing along the lines of the below should work, but as suggested in the comment above this will then error on the system schemas / users.
BEGIN
DECLARE
CURSOR c1 IS
SELECT username FROM dba_users WHERE username LIKE '${USER}%';
BEGIN
FOR user_rec IN c1 loop
IF ${DROP_AB}='Y' THEN
EXECUTE IMMEDIATE 'DROP USER ' ||user_rec.username|| ' CASCADE';
ELSE
IF user_rec.username != ${USER}AB THEN
EXECUTE IMMEDIATE 'DROP USER ' ||user_rec.username|| ' CASCADE';
END IF;
END IF;
END LOOP;
END;
END;
/

Resources