1

Does anybody know how to run all the lines generated from the following query as scripts on their own right?

select 'DROP TABLE '||table_name||' CASCADE CONSTRAINTS;' from user_tables;

What I'm basically trying to do, is delete all the user tables and constraints on my DB (this is oracle). The output I get is correct, but I want to know how I would run all the lines without copy/pasting.

Also, is there a more efficient way to drop all tables (including constraints)?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
serv-bot 22
  • 1,278
  • 2
  • 10
  • 13

4 Answers4

4
begin
  for i in (select table_name from user_tables)
  loop
    execute immediate ('drop table ' || i.table_name || ' cascade constraints');
  end loop;
end;
/

Justin Cave brought up an excellent point - the following will drop tables within the user's schema starting at the outermost branches of the hierarchy of dependencies, assuming all foreign keys reference the primary key, not a unique constraint. Tables without primary keys would be dropped last.

begin
  for i in (select parent_table, max(tree_depth) as tree_depth
              from (select parent.table_name as parent_table,
                           child.constraint_name as foreign_key, 
                           child.table_name as child_table,
                           LEVEL AS TREE_DEPTH
                      from (select table_name, constraint_name
                              from USER_constraints
                             where constraint_type = 'P'
                           ) parent 
                           LEFT JOIN
                           (SELECT TABLE_NAME, CONSTRAINT_NAME, 
                                   r_constraint_name
                              FROM USER_CONSTRAINTS
                             WHERE CONSTRAINT_TYPE = 'R') child
                              on parent.constraint_name = 
                                    child.r_constraint_name
                           CONNECT BY NOCYCLE 
                             (PRIOR CHILD.TABLE_NAME = PARENT.TABLE_NAME)
                   UNION
                   select DT.table_name as parent_table,
                          NULL AS FOREIGN_KEY, NULL AS CHILD_TABLE,
                          0 AS TREE_DEPTH
                     FROM USER_TABLES DT
                    WHERE TABLE_NAME NOT IN
                          (SELECT TABLE_NAME
                             FROM USER_CONSTRAINTS
                            WHERE CONSTRAINT_TYPE = 'P')
                   )
             group by parent_table
             order by 2 desc
           )
  loop
    execute immediate ('drop table ' || i.parent_table || 
                       ' cascade constraints');
  end loop;
end;
/
Adam Musch
  • 13,286
  • 2
  • 28
  • 32
3

The quick and dirty solution would be to do something like

FOR x IN (SELECT * FROM user_tables)
LOOP
  BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE ' || x.table_name || 
                        ' CASCADE CONSTRAINTS';
  EXCEPTION
    WHEN others THEN
      dbms_output.put_line( 'Failed to drop ' || x.table_name ); 
  END;
END LOOP;

and run that a number of times until all the tables had been dropped. This will take multiple passes because you can't drop a parent table while there are still child tables with foreign keys that reference the parent.

The cleaner option would be to write a hierarchal query against the data dictionary to get the child tables, the parents of those children, the grandparents, etc. and to walk the tree to drop the appropriate objects. That should avoid errors but it would require a bit more work to code.

Justin Cave
  • 227,342
  • 24
  • 367
  • 384
1

execute immediate - pass in the generated string

Randy
  • 16,480
  • 1
  • 37
  • 55
  • `execute inmediate select 'DROP TABLE '||table_name||' CASCADE CONSTRAINTS' from user_tables`? I'm getting the following error: **ERROR at line 1: ORA-06550: line 1, column 17: PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: := . ( @ % ; The symbol ";" was substituted for "SELECT" to continue.** – serv-bot 22 Apr 11 '11 at 21:11
  • Thank you! This was sort of the answer, but I needed some more explanations. – serv-bot 22 Apr 11 '11 at 21:43
1

It is generally more efficient when dropping tables to use the truncate statement.

You can execute dynamic scripts using the execute immediate command

Scott Mackay
  • 1,194
  • 10
  • 34
  • Thanks! How would I deal with the constraints while using the truncate statement? – serv-bot 22 Apr 11 '11 at 21:16
  • 1
    First thing that comes to mind is to check for constraints using the select * from all_constraints where table_name = 'mytable' and drop them in a loop using execute immediate, same as you're doing for your tables but there may be a better way. – Scott Mackay Apr 11 '11 at 21:19