how to move indexes to another tablespace
select owner, index_name, TABLE_NAME, a.TABLESPACE_NAME
from all_indexes a where a.TABLE_NAME = 'REFUND';
ALTER INDEX CBS.PK_REFUND_ID REBUILD TABLESPACE T_IDX;
ORA-14086: A partitioned index may not be rebuilt as a whole.
I can't execute this statement because I don't know in which partition the index is
ALTER INDEX PK_REFUND_ID REBUILD PARTITION xxxxxx TABLESPACE T_IDX;
Because you also need partition name info which can be reached from user[all/dba]_tab_partitions dictionary view. If you got the related partition name, then
ALTER INDEX PK_REFUND_ID REBUILD PARTITION PR_REFUND_OLD [ONLINE];
might be used just to rebuild the index.
or
ALTER INDEX PK_REFUND_ID REBUILD PARTITION PR_REFUND_OLD [ONLINE] TABLESPACE T_IDX;
might be used to move the index of the partition to a different tablespace. Using ONLINE option would suit well for the tables currently having DML activity.
Use the following code in order to run as a batch job
DECLARE
v_ts_name VARCHAR2(35) := 'T_IDX';
BEGIN
FOR c IN
(
SELECT 'ALTER INDEX '||i.index_name||' REBUILD PARTITION '||p.partition_name||
' ONLINE TABLESPACE '||v_ts_name AS command
FROM user_part_indexes i
JOIN user_ind_partitions p
ON p.index_name = i.index_name
AND i.table_name = 'REFUND'
AND p.tablespace_name != v_ts_name
)
LOOP
EXECUTE IMMEDIATE c.command;
END LOOP;
END;
/
Related
I am trying to create a index organized table in oracle 11. I create the index organized table and insert the row from another table.
create table salIOT (
mypk ,
cid ,
date,
CONSTRAINT sal_pk PRIMARY KEY (mypk)
) ORGANIZATION INDEX
AS Select * from another table;
But the leaf blocks are empty when I query
SQL> Select owner, index_name, table_name, leaf_blocks from all_indexes where table_name like 'SALIOT';
Am I missing something here?
You still need to gather statistics on the table, something like:
exec dbms_stats.gather_table_stats('ABC', 'IOTTableName')
(assuming 'ABC' is your username; change as needed) - then re-run your SELECT against ALL_INDEXES and you will see how many leaf blocks you have.
CREATE INDEX Index_name ON tab_name
(Co1)
GLOBAL PARTITION BY HASH (Co1);
I need to drop this global index having list partition with new column added
CREATE INDEX Index_name ON tab_name
(Co1,co2)
GLOBAL PARTITION BY HASH (Co1);
When I tried to drop and recreate the global indexes , I couldn't see the partitions
select partition_name from user_ind_partitions where index_name = 'Index_name'
I have specified the no of partitions at the end and its now able to retrieve all list partitions from table for the specified index .
CREATE INDEX Index_name ON tab_name
(Co1,co2)
GLOBAL PARTITION BY HASH (Co1,col2)
PARTITIONS 16;
Problem
I have sql scripts which may use different tablespaces for different database users.
In order to remain flexible with the table creation I'd like to keep only 1 script and apply it to the various users. For that purpose I have something like this:
Tablespaces:
CREATE TABLESPACE MY_TABLESPACE DATAFILE 'MY_TABLESPACE.dat' SIZE 40M ONLINE;
CREATE TABLESPACE MY_INDEXSPACE DATAFILE 'MY_INDEXSPACE.dat' SIZE 40M ONLINE;
And the table creation script:
define default_tablespace = 'MY_TABLESPACE';
define default_indexspace = 'MY_INDEXSPACE';
drop table test_table;
create table test_table ( id number ) tablespace &default_tablespace;
create index my_index on test_table( id) tablespace &default_indexspace;
i. e. I can't set a default tablespace for the user, because the index uses a different tablespace.
Question
Is it possible to override the definition of default_tablespace and default_indexspace depending on e. g. an environment variable?
Something like:
define default_tablespace = isEnviromentVariableSet( 'OTHER_TABLESPACE') ? getEnvironmentVariable( OTHER_TABLESPACE) : 'MY_TABLESPACE';
That way I could use different tablespaces whenever I invoke the script externally by some utility and at the same time I could keep the default tablespace.
Thank you very much for the help!
In DDL operation (create, drop, etc.) u can't use variables.
Easy way is use pl/sql anonymous block like this.
declare
my_tabable_space varchar2(100) default 'my_some_tablespace';
other_tablespace varchar2(100);
begin
DBMS_SYSTEM.get_env('OTHER_TABLESPACE',other_tablespace);
if other_tablespace is not null then
my_tabable_space := other_tablespace ;
end if;
execute immediate 'create table test_table ( id number ) tablespace' || my_tabable_space;
end;
/
and for select ENV variable u can use DBMS_SYSTEM.get_env ('NAME of VARIABLE', my_variable) but this package need DBA right (i think.. :-) )
I need to truncate a table that has around 40 million records in it. i guess it is ok to REUSE STORAGE for the table since new data will be inserted after the truncate.
I need to know
approximately how much time the command
TRUNCATE TABLE <tablename> REUSE STORAGE; would take.
Can this be done offline, so that the operations/ commands on the DB
don't get affected?
Based on "so that the operations/ commands don't get affected", it sounds like you'd like to replace the contents of a table with "good" values, without anyone seeing an empty table. If users/processes need to be able to continue making changes to the table while you switch out the contents, you'll need to research DBMS_REDEFINITION. If this is a read-only table (in other words, you can do this operation while nobody is inserting/updating/deleting its contents), there's a nice DIY approach that takes advantage of partition exchanging:
1) Create a table which has identical partitioning and indexing as original, and has the desired "good" rows.
2)
IF YOUR TABLE IS PARTITIONED:
CREATE TABLE <tablename>_TMP AS SELECT * FROM <tablename> WHERE 1=0;
-- Add any local indexes on <tablename> as standard indexes on <tablename_tmp>
BEGIN
FOR R IN (SELECT * FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = <tablename>)
LOOP
EXECUTE IMMEDIATE
'INSERT INTO <tablename>_TMP'
||' SELECT * FROM <good_data_tablename> PARTITION ('||R.PARTITION_NAME||')';
EXECUTE IMMEDIATE
'ALTER TABLE <tablename>_TMP'
||' EXCHANGE PARTITION WITH TABLE <tablename> PARTITION ' || R.PARTITION_NAME
||' INCLUDING INDEXES WITHOUT VALIDATION UPDATE GLOBAL INDEXES';
EXECUTE IMMEDIATE
'TRUNCATE TABLE <tablename>_TMP';
END LOOP
END;
/
DROP TABLE <tablename>_TMP ;
IF YOUR TABLE IS NOT PARTITIONED:
CREATE TABLE <tablename>_TMP
PARTITION BY RANGE (<non-null-column>)
(PARTITION ALL_DATA values less than (maxvalue))
AS SELECT * FROM <good_data_tablename>;
-- Add any <tablename> indexes as local indexes on <tablename>_TMP
ALTER TABLE <tablename> EXCHANGE PARTITION WITH TABLE <tablename>_TMP INCLUDING INDEXES WITHOUT VALIDATION;
DROP TABLE <tablename>_TMP ;
I want to disable NOT NULL constraints into a table to insert data for test but I can't find a way to disable unnamed constraints.
I found enough info to disable named constraints, but I couldn't find a example to disable unnamed NOT NULL constraint.
I would like to implement this without querying the data dictionary, but... I'm willing to do that if its the only way. But I would like to use a clean ALTER TABLE DDL.
You will need to query the data dictionary, something like this will disable all constraints on the table. Be aware though, that this will disable the constraint system wide, not just for your session.. Perhaps what you really want is to defer the constraint?
drop table testxx
drop table testxx succeeded.
create table testxx ( id number not null )
create table succeeded.
select status from user_constraints where table_name = 'TESTXX'
STATUS
--------
ENABLED
1 rows selected
begin
for cnames in ( select table_name,constraint_name from user_constraints where table_name = 'TESTXX' ) loop
execute immediate 'alter table ' || cnames.table_name || ' disable constraint ' || cnames.constraint_name;
end loop;
end;
anonymous block completed
select status from user_constraints where table_name = 'TESTXX'
STATUS
--------
DISABLED
1 rows selected
You can also just alter the column as follows
create table test_null (col_n number not null);
alter table test_null modify col_n number null;