Oracle: Moving Data to a new Tablespace

The worst thing about being the most technically competent person in a company is that all too often, the buck stops at my desk.  I can’t complain – it’s a problem of my own making; I’m too lazy to pass on knowledge in a usable format, so I end up having to do a lot of the work.

One of my regular tasks is sorting out the database on our Support server.  This is a bit of a nightmare, since the users of that server are all – at least in their own minds – admin types, so configurations and usage changes on a daily basis.

Today – we ran out of space.  This isn’t as bad as it sounds, since I’ve put a restriction in place to limit any database file to 8GB (this is a limit enforced by my rather lame backup practices).  I knew the problem – one of our support databases was on the “USERS” tablespace, instead of the appropriate customer-specific tablespace.

Thanks to the guys at DBA Sensation, finding the correct commands to move Tables, Indexes and even LOB Segments to a new tablespace was trivial… But here’s a very useful script that generates a full set of commands to move all of a given user’s data from one tablespace to another…

SELECT CASE
     WHEN segment_type = 'TABLE' THEN
          'ALTER TABLE '||seg.owner||'.'||seg.segment_name ||' MOVE TABLESPACE '||'&TARGET_TBSP'||';'
     WHEN segment_type = 'INDEX' THEN
          'ALTER INDEX '||seg.owner||'.'||seg.segment_name ||' REBUILD TABLESPACE '||'&TARGET_TBSP'||';'
     WHEN segment_type = 'LOBINDEX' THEN
          'ALTER TABLE '||seg.owner||'.'||lob.table_name ||' MOVE LOB('||lob.column_name||') ' ||'STORE AS (TABLESPACE '||'&TARGET_TBSP'||');'
     ELSE '/* Segment '||seg.segment_name ||' is of type: '||segment_type||' */'
     END AS sql_command
FROM dba_segments seg, dba_lobs lob
WHERE seg.owner = '&SOURCE_OWNER'
     AND seg.tablespace_name = '&SOURCE_TBSP'
     AND seg.owner = lob.owner(+)
     AND seg.segment_name = lob.index_name (+)
GROUP BY seg.owner, seg.segment_name, 
     seg.segment_type, seg.tablespace_name, 
     lob.table_name, lob.column_name
ORDER BY seg.segment_type DESC, seg.segment_name;

A word of warning: This will work for all tables, indexes and LOB segments, but will not handle any tables that have a LONG datatype. OraFAQ has a helpful thread about this – the simple answer is that LONG datatypes don’t support the MOVE command.

Sphere: Related Content

Tags: , , ,


Leave a Reply