Oracle - drop table constraints without dropping tables - sql

I'm doing some bulk migration of a large Oracle database. The first step of this involves renaming a whole load of tables as a preparation for dropping them later (but I need to keep the data in them around for now). Any foreign key constraints on them need to be dropped - they shouldn't be connected to the rest of the database at all. If I were dropping them now I could CASCADE CONSTRAINTS, but rename simply alters the constraints.
Is there a way I can drop all of the constraints that CASCADE CONSTRAINTS would drop without dropping the table itself?

You can do it with dynamic SQL and the data dictionary:
begin
for r in ( select table_name, constraint_name
from user_constraints
where constraint_type = 'R' )
loop
execute immediate 'alter table '|| r.table_name
||' drop constraint '|| r.constraint_name;
end loop;
end;
If the tables are owned by more than one user you'll need to drive from DBA_CONSTRAINTS and include OWNER in the projection and the executed statement. If you want to touch less than all the tables I'm afraid you'll need to specify the list in the WHERE clause, unless there's some pattern to their names.

You can disable/re-enable constraints without dropping them. Take a look at this article.

Related

How to list all tables that have data in it?

I have around 2000 tables that most of them are not in use and do not have any data in them.
I know how to list all tables as below
SELECT owner, table_name FROM ALL_TABLES
But I do not know how to list the one that has at least one row of data in it.
Is there anyway to do that?
There are a few ways you could do this:
Brute-force and count the rows in every table
Check the table stats
Check if there is any storage allocated
Brute force
This loops through the tables, counts the rows, and spits out those that are empty:
declare
c integer;
begin
for t in (
select table_name from user_tables
where external = 'NO'
and temporary = 'N'
) loop
execute immediate
'select count(*) from ' || t.table_name
into c;
if c = 0 then
dbms_output.put_line ( t.table_name );
end if;
end loop;
end;
/
This is the only way to be sure there are no rows in the table now. The main drawback to this is it could take a looooong time if you a many tables with millions+ rows.
I've excluded:
Temporary tables. You can only see data inserted in your session. If they're in use in another session you can't see this
External tables. These point to files on the database server's file system. The files could be temporarily missing/blank/etc.
There may be other table types with issues like these - make sure you double check any that are reported as empty.
Check the stats
If all the table stats are up-to-date, you can check the num_rows:
select table_name
from user_tables ut
where external = 'NO'
and temporary = 'N'
and num_rows = 0;
The caveat with this is this figures may be out-of-date. You can force a regather now by running:
exec dbms_stats.gather_schema_stats ( user );
Though this is likely to take a while and - if gathering has been disabled/deferred - might result in unwanted plan changes. Avoid doing this on your production database!
Check storage allocation
You can look for tables with no segments allocated with:
select table_name
from user_tables ut
where external = 'NO'
and temporary = 'N'
and segment_created = 'NO';
As there's no space allocated to these, there's definitely no rows in them! But a table could have space allocated but no rows in it. So it may omit some of the empty tables - this is particularly likely for tables that did have rows in the past, but are empty now.
Final thoughts
It's worth remembering that a table with no rows now could still be in use. Staging tables used for daily/weekly/monthly loads may be purged at the end of the process; removing these will still break your apps!
There could also be code which refers to empty tables which work as-is, but would error if you drop the table.
A better approach would be to enable auditing, then run this for "a while". Any tables will no audited access in the time period are probably safe to remove.

Oracle: Script to verify that objects belong to their tablespaces

I have 2 tablespaces, one to store tables and other on to store indexes. I created a script that can be run in any of my schemas and it will move objects (tables or indexes) to their respective tablespaces.
However, I am failing to come up with a script that will verify that objects have been moved to the correct tablespaces (meaning tables have been moved to the table tablespace, and indexes have been moved to the index tablespace).
Any thoughts?
You can use the query below to get the information through a spesific schema :
select t.table_name, t.tablespace_name as "TS Name For Table",
i.index_name, i.tablespace_name as "TS Name For Indexes"
from user_tables t
join user_indexes i on i.table_name = t.table_name
order by t.table_name, i.index_name;

Temporarily Disabling Constraints in Oracle Database

I have an Oracle SQL delete statement that is taking a very long time to run. It's very simple, something like:
delete from table
where fy = 2016
I also manually tried deleting one of the ~2500 rows I need to get rid of in TOAD and it's taking about 6 minutes to delete a single row.
I think the reason for this is that the table has a lot of constraints on it, so I'm wondering if I can somehow change my delete statement in such a way that it can bypass the constraints or disable them temporarily in order to do it much faster? If so, how can I re-enable them afterwards?
6 minutes to delete a single row does not sound like an issue with constraints on the table. There are three reasonably likely mechanisms that would cause that level of performance problem. Most to least likely in my experience
The table is the parent to one or more large child tables. The child tables have an enforced foreign key reference to the parent table but the foreign key column is not indexed in the child table. If this is the case, the issue is that Oracle has to do a full scan of the table every time you delete a row from the parent in order to verify that there are no orphans. You could go to each child table and drop the foreign key but it would almost certainly make more sense to index the foreign key column in the child table(s). It is very rare that you want to have unindexed foreign keys.
There is a trigger on the table and the trigger is doing something that takes 6 minutes. You'd have to look at the trigger code to see exactly what was taking so long there.
You are doing a single-row delete as a transaction and you have an on commit materialized view that needs to be updated as a result of the change. It's hard to come up with a way to build something like this that would take 6 minutes to run but there are certainly ways to make this slow.
As you stated; the reason is foreign keys to that table. You should disable that keys before delete and enable them after delete. You can use following script to enable/disable keys of a specific table.
declare
l_constraint_sql varchar2(1024);
l_op_type varchar2(10) := 'ENABLE';
begin
-- Test statements here
for r in (select a.*
from user_constraints a, user_constraints b
where a.constraint_type = 'R'
and a.r_constraint_name = b.constraint_name
and a.r_owner = b.owner
and a.owner = 'FAYDIN' --schema
and b.table_name = 'GEN_KOD' --table you want to disable constraints
) loop
l_constraint_sql := 'alter table ' || r.TABLE_NAME ||
' ' || l_op_type || ' constraint ' || r.CONSTRAINT_NAME || '';
--uncomment following line to execute
--execute immediate l_constraint_sql;
dbms_output.put_line(l_constraint_sql);
end loop;
end;

Is any tool help me to query table by CONSTRAINTS rule?

I have a big database, the database have more than 1000 tables and have many
table constraints rules. To remember all table constraints rule is too hard for me.Every day i need write many simple sql to query several tables. Writing so many sqls by hand is waste my time. Is there any tool to save my time to help me query table by CONSTRAINTS rule?
if database is Oracle , you didn't try data dictionary ?
USER_CONSTRAINTS / ALL_CONSTRAINTS / DBA_CONSTRAINTS table ?
for query constrains on certain tables that own by current user
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, R_CONSTRAINT_NAME, STATUS
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = 'CRUISES';
or you can try all constraints in table that user have right to query using ALL_CONSTRAINTS table
or you can try on database level constraint using DBA_CONSTRAINTS table
both 3 tables share same column structure , so I won't repeat much .
If you want a GUI tool, you could do worse than any of the following products:
SQL Developer (Oracle)
TOAD (Quest)
PL/SQL Developer (Alround Automation)

Difference Between Drop And Drop Purge In Oracle

I am using Oracle Database and I am a bit confused about Drop and Purge Commands. In fact for me both does the same thing. Removes the table with schema from database. What is the main difference between these two?
Drop Table Tablename;
Drop Table Tablename Purge;
Normally, a table is moved into the recycle bin (as of Oracle 10g), if it is dropped. However, if the purge modifier is specified as well, the table is unrecoverably (entirely) dropped from the database.
Oracle Database 10g introduces a new feature for dropping tables. When you
drop a table, the database does not immediately release the space associated with the
table. Rather, the database renames the table and places it in a recycle bin, where it can
later be recovered with the FLASHBACK TABLE statement if you find that you
dropped the table in error.
If you want to immediately release the space associated with the table at the time
you issue the DROP TABLE statement, then include the PURGE clause as follows.
DROP TABLE employees PURGE;
Specify PURGE only if you want to drop the table and release the space
associated with it in a single step. If you specify PURGE, then the database does not
place the table and its dependent objects into the recycle bin.
NOTE: You cannot roll back a DROP TABLE statement with the PURGE
clause, and you cannot recover the table if you drop it with the PURGE clause. This
feature was not available in earlier releases.
A link to asktom article: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32543538041420
Basically with oracle10, all dropped tables go into recycle bin from where they can be undropped. With purge you basically skip the recycle bin part and you drop the table without an option to undo the action.
SQL>drop table table_name;
This command deletes the table named table_name, but internally it is moved to recycle bin of oracle (which is just similar to deleting any file/folder using Delete key on windows os).
Benefits:
1. We will be able to restore the above deleted table if required.
Drawbacks:
1. Still occupies some amount of memory.
SQL>drop table table_name purge;
This command deletes the table table_name completely from the database (which is similar to deleting any file/folder using Shift + Delete key on windows OS).
The Benefits and Drawbacks will be vice-verse of the above.
The below statement will drop the table and place it into the recycle bin.
DROP TABLE emp_new;
The below statement will drop the table and flush it out from the recycle bin also.
DROP TABLE emp_new PURGE;
It’s clear from #Randy comment, just to add on:
(1) Drop Table Tablename:
Without purge, the table can be in the RECYCLEBIN or USER_RECYCLEBIN; which can be restored using the command FLASHBACK. This is similar to files we delete in our windows desktop, which move to the recycle bin, and can be restored back.
(2) Drop Table Tablename Purge:
If Drop is given along with Purge, its tablespace is released and cannot be restored. (Like Shift+Delete in desktop)
Following example gives practical example:
create table test_client (val_cli integer, status varchar2(10));
drop table test_client ;
select tablespace_name from all_tables where owner = 'test' and table_name = 'TEST_CLIENT';
SELECT * FROM RECYCLEBIN where ORIGINAL_NAME='TEST_CLIENT';
SELECT * FROM USER_RECYCLEBIN where ORIGINAL_NAME='TEST_CLIENT';
FLASHBACK TABLE test_client TO BEFORE DROP;
select tablespace_name from all_tables where owner = 'test' and table_name = 'TEST_CLIENT';
drop table test_client purge;
select tablespace_name from all_tables where owner = 'test' and table_name = 'TEST_CLIENT';
drop table table_name purge;
By using this query what happened:-
Normally, a table is moved into the recycle bin (as of Oracle 10g), if it is dropped.But still occupied the memory in database so to release the the memory for another object we can use the the Purge clause.