Oracle - Move all tables and reclaim free space - oracle

I have this query:
select file_id, block_id first_block, block_id+blocks-1 last_block,
segment_name
from dba_extents
where tablespace_name = 'USERS'
union all
select file_id, block_id, block_id+blocks-1, 'free'
from dba_free_space
where tablespace_name = 'USERS'
order by file_id, first_block DESC;
It shows lot of "free" segments in between. There are lot of tables which are coming in between.
I move the tables using:
Alter table table_name move;
I have 2000 such tables. Is there a way on how I can move it altogether so I can reclaim all the free space from the tablespace?

To achieve your goal you have to move all objects in the tablespace, not just tables.
At least you have to move tables and then rebuild all their indexes because when you move a table all indexes built on this table are invalidated.
You can not move all tables all together but you can obtain all commands in the following way:
select 'alter table ' ||table_name ||' move;'
from dba_tables where tablespace_name = 'YOURTABLESPACENAME';
To rebuild indexes:
select 'alter index ' ||index_name ||' rebuild;'
from dba_indexes where tablespace_name = 'YOURTABLESPACENAME' and status <>'VALID';
Be careful: this procedure is not complete, you can have indexes of different kind.
Note: to obtain best results you should move objects in a different tablespace.
A simpler approach can be the one explained here: this article describe how to use the shrink command against Oracle database tables to reclaim wated space.
If you want a detailed procedure give me the result of the following query:
select distinct segment_type from dba_segments where tablespace_name='YOURTABLESPACENAME';

Related

Unable to view tablespace name for a partitioned table

I am unable to get the tablespace information for a partitioned table.
I have tried querying tablespace_name from dba_tables but the value was null. Let me know the reason to this and also from where can I view the tablespace_name for a partitioned table.
select tablespace_name
from dba_tables
where table_name = 'XXXXX';
The result was null.
Please let me know how can I get the tablespace information coz I am trying to move the partitions to a new tablespace.Also let me know the impact of it.
The reason is that you could have each partition in a different tablespace, so the information at a table level does not exist and you need to check the partitions.
Oracle doc for this
You may need DBA_TAB_PARTITIONS
select tablespace_name
from dba_tab_partitions
where table_name='...'
and table_owner = '...'

Finding tablespace size on oracle without dba_* metatables

I need to find the current tablespace size for a db in Oracle 10g. Looking around, I've found many scripts that determine size using tables like dba_extents, but the database I'm using has none of these dba_* tables.
(I'm using this as a proxy for finding table size, which is complicated because most of the table size is in blobs.)
The DBA_* views are part of the "Static Data Dictionary Views" Generally there are three versions of every view, DBA_ that shows everything, ALL_ that shows what you have access to, and USER_ that will show what you own, and will not have the OWNER column.
For example DBA_TABLES has all tables, ALL_TABLES are the table you can select from, and USER_TABLES are the tables you own.
The views are documented in "Static Data Dictionary Views". A good resource if you need to translate from DBA_ to ALL_ or USER_.
Unfortunately _EXTENTS only comes in a DBA and USER version. So if want information on objects you can access but do not own, you will need to ask your resident DBA for help.
The dba_* views are part of the data dictionary, which exists in every Oracle database. They're in the sys schema, and if you can't query them, it probably just means you don't have SELECT access to them.
If the table you want to check is in your schema, you can replace e.g. dba_extents with user_extents and the query should work.
Here's my suggestion for a script to tell the size of a table in your schema (indexes included):
select segment_name, segment_type, bytes/1024/1024 as size_in_mb
from user_segments
where segment_name = :YOUR_TABLE
or segment_name in (select segment_name from user_lobs where table_name = :YOUR_TABLE)
or segment_name in (select index_name from user_indexes where table_name = :YOUR_TABLE);

How to specify tablespace_name in SQLPlus Oracle select

My setup looks like this
SQL> SELECT tablespace_name, table_name
FROM all_tables
WHERE tablespace_name = 'MYSPACE';
TABLESPACE_NAME TABLE_NAME
-------------------------- ------------------------------
MYSPACE MYTABLENAME
MYSPACE MYOTHERTABLENAME
Now I'd like to SELECT * FROM MYSPACE.MYTABLENAME; but that's apparently not how you do it.
ERROR at line 1:
ORA-00942: table or view does not exist
My expected result would be to get all records from that table. Like I would if it was MySQL.
Thanks
You are selecting from tablespace, which is not the same as your Owner/Schema name. Thats why. For example the tablespace SYSTEM has owner SYS. You do select from Sys.xxx;
Ok.
SELECT owner, tablespace_name, table_name
FROM all_tables
WHERE tablespace_name = 'MYSPACE';
And then
select * from [ owner ].[ table_name ];
(worth to mention: select .. from dba_tables / user_tables)
Tables are not owned by a tablespace. A tablespace is a logical storage storage structure. When you create a table (or index) you specify which tablespace its contents should be stored in. Unless you're doing DBA tasks, you don't really need to know which tablespace(s) your data is stored in.
You may just be confusing terms. Tables are owned by schemas. If you query the owner column instead of tablespace_name you might see something like:
SQL> SELECT owner, table_name
FROM all_tables
WHERE tablespace_name = 'MYSPACE';
OWNER TABLE_NAME
-------------------------- ------------------------------
MYUSER MYTABLENAME
MYUSER MYOTHERTABLENAME
And you can then query from that with
SELECT * FROM MYOWNER.MYTABLENAME;
Of course, if the owner is actually you anyway, then you don't need to prefix the table name with the schema; you can just select FROM MYTABLENAME. (You may also have synonyms or session settings that make the schema prefix unnecessary, but that's getting a a bit off-topic). And if you own the table you'll see it in USER_TABLES as well.

Table not created in specific tablespace - Oracle

I am a moderate user of Oracle and I had to create some of the tables in specified table space as shown below.
create table t_abc tablespace abc_tbspc as select * from abc;
create table t_xyz tablespace abc_tbspc as select * from xyz;
After running these through jobs (file containing around 5 tables to be created in a single tablespace), I could see that the table t_abc is created in abc_tbspc ; but the table t_xyz is assigned to null when I query the all_tables. Not sure why the 2nd table is not created in the specified tablespace even though there is abundant space in the table space.
TABLESPACE_NAME will be null for one of these reasons:
Temporary Temporary tables use a temporary tablespace.
Index Organized Index-organized tables store data in an index, not in a heap.
Partitioned Each partition could have a different tablespace, there is not necessarily one tablespace for the whole table.
External External tables do not store their data in a tablespace.
Your code should not meet one of the conditions above; did you leave out some details? I ran the query below to look for other cases where TABLESPACE_NAME is null but could not find any.
select *
from dba_tables
where tablespace_name is null
and (temporary is null or temporary <> 'Y') -- #1
and (iot_type is null or iot_type <> 'IOT') -- #2
and (partitioned is null or partitioned <> 'YES') -- #3
and (owner, table_name) not in -- #4
(select owner, table_name from dba_external_tables)

How do I get all records associated with a record in an aggregate root table

For testing purposes, I would like to generate an insert script for all records in all tables associated with a particular record in one of the root tables. For example, I might have a "Participant" table, which has any number of associated entries in the "Documents" table, which in turn has any number of associated entries in the "PrintRequests" table and so on and so forth. I have hundreds of these tables in the database.
Is there any way to select/script out all the records in all tables that are associated with for example ParticipantId = 1? This way, for a representative participant, I can extract all the associated records in all the tables.
One of my ideas was to restore a back up of the full database, modify all foreign key constraints to have cascade delete and then delete everything that is not participantid = 1 and let the database take care of deleting everything that is not related to the participant of interest and then script out the entire database of what remains.
For this, I might have to drop and recreate all the constraints, which I am unsure about how to do across the entire database.
Alternately, are there any other tools that would be able to do this? A migration tool for example that can take a query and only migrate the records and associated child records of that query?
While it is entirely possible to build scripts to walk through all the primary key and foreign key constraints and, via liberal use of dynamic SQL, generate these scripts, doing so would be a non-trivial undertaking. I would strongly suspect that you would be better served using a product like DataBee to generate your data subset.
You can script it creating dynamic SQL statements, but I think it is really lots of work. I think you will be faster to just find all the tables with a column "ParticipantId" with something like this
select * from all_tab_columns where column_name = 'PARTICIPANTID'
And then do some fast edit / replace / other sort of script action to generate yourself the delete statements.
Regarding the constraints. This is similar. Getting all the constraints with
SELECT owner, table_name, constraint_name
FROM dba_constraints
where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID')
You switch on and off constraints using
ALTER TABLE <table name> ENABLE/DISABLE constraint <constraint name>;
Maybe this you could do with a loop. Borrowing from this page
begin
for i in
(select constraint_name, table_name from user_constraints where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID')
) LOOP
execute immediate 'alter table '||i.table_name||' disable constraint '||i.constraint_name||'';
end loop;
end;
I am not sure about your cascading delete thing but the above gives a bit an idea how the delete would look like:
begin
for i in
(select constraint_name, table_name from user_constraints where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID')
) LOOP
execute immediate 'delete from '||i.table_name||' where participantid = ''1'' ';
end loop;
end;
Hope it helps.

Resources