How to rename index which is another tablespace oracle? - oracle

I want to rename an index which is in another tablespace.
Is the following SQL (oracle) valid?
ALTER INDEX OLD_INDEX_NAME RENAME TO NEW_INDEX_NAME TABLESPACE OTHER_TABLE_SPACE;

Tablespace doesn't matter; you aren't relocating index, just renaming it.
Sample table in one tablespace:
SQL> create table test (id number) tablespace user_rw;
Table created.
SQL> select table_name, tablespace_name from user_tables where table_name = 'TEST';
TABLE_NAME TABLESPACE_NAME
--------------- --------------------
TEST USER_RW
Index on that table, in another tablespace:
SQL> create index i1test on test (id) tablespace rwmig;
Index created.
SQL> select index_name, table_name, tablespace_name
2 from user_indexes where index_name = 'I1TEST';
INDEX_NAME TABLE_NAME TABLESPACE_NAME
--------------- --------------- --------------------
I1TEST TEST RWMIG
Rename index:
SQL> alter index i1test rename to i1test_new;
Index altered.
Result: index is renamed, tablespace remained the same (why wouldn't it?):
SQL> select index_name, table_name, tablespace_name
2 from user_indexes where index_name = 'I1TEST_NEW';
INDEX_NAME TABLE_NAME TABLESPACE_NAME
--------------- --------------- --------------------
I1TEST_NEW TEST RWMIG
SQL>

Related

Find all index that needs to be rebuilt

I have been searching for a way to find all the indices that needs to be re-built. But couldn't find a syntax on the web.
Is there a syntax to find the same?
It is unusable. Have a look at the following example:
SQL> create table test (id number);
Table created.
SQL> create index i1t on test (id);
Index created.
Make the index unusable:
SQL> alter index i1t unusable;
Index altered.
SQL> select index_name from user_indexes where status = 'UNUSABLE';
INDEX_NAME
------------------------------
I1T
Rebuild it and check its status again:
SQL> alter index i1t rebuild;
Index altered.
SQL> select index_name from user_indexes where status = 'UNUSABLE';
no rows selected
SQL>
Of course, you wouldn't rebuild them manually - write a script to do it for you. For example:
SQL> set serveroutput on;
SQL> begin
2 for cur_r in (select index_name from user_indexes
3 where status = 'UNUSABLE'
4 )
5 loop
6 dbms_output.put_line('Rebuilding index ' || cur_r.index_name);
7 execute immediate 'alter index ' || cur_r.index_name || ' rebuild';
8 end loop;
9 end;
10 /
Rebuilding index I2T
Rebuilding index I1T
PL/SQL procedure successfully completed.
SQL>

Why truncate table does not change the Last DDL Date?

When I run the following code, I notice that Last DDL Date has not changed.
execute immediate 'truncate table my_table';
What is the problem?
thanks in advance
The truncate table only truncates the table if it is not empty.
If the table is empty then it is not truncated when you execute the truncate table command.
See the demo here:
SQL> select OBJECT_NAME, LAST_DDL_TIME from user_objects where OBJECT_NAME = 'CONTR';
OBJECT_NAME LAST_DDL_TIME
------------ --------------------
CONTR 13-nov-2019 11:45:53
SQL> truncate table CONTR; -- empty table
Table truncated.
SQL> select OBJECT_NAME, LAST_DDL_TIME from user_objects where OBJECT_NAME = 'CONTR';
OBJECT_NAME LAST_DDL_TIME
------------ --------------------
CONTR 13-nov-2019 11:45:53
SQL> INSERT INTO CONTR VALUES (1,1,1,1); -- filling values in the table
1 row created.
SQL> commit;
Commit complete.
SQL> truncate table CONTR;
Table truncated.
SQL> select OBJECT_NAME, LAST_DDL_TIME from user_objects where OBJECT_NAME = 'CONTR';
OBJECT_NAME LAST_DDL_TIME
------------ --------------------
CONTR 13-nov-2019 11:47:46
SQL> -- time is changed now
Cheers!!
I found the answer.
The thing is :
Table is empty.
When a table is empty your truncate ddl does not
change the Last DDL Date.

Extra entries in recycle bin when table dropped

I have created a table TESTTABLE28.
Then I dropped the table.DROP TABLE TESTTABLE28;
The show parameter recyclebin; value was set to on.
When I checked the Recycle Bin, observed some other entries along with TESTTABLE28 are listed,
Once I flashback table TESTTABLE28 to before drop; to restore the table, these extra entries are also moved.
What is this values and why it didn't come, when I dropped another table TESTTABLE31 which has only one varchar2 column?
UPDATE
Also how can I restore the constraints which is showing BIN$5lpccCurTNWwCbOSxCK29w==$1 now instead of TESTTABLE28_PK.
Because you have LOB columns in your table you also have segments and indices to them:
SQL> create table t_lb (x int, y clob, z blob);
SQL> col column_name format a10
SQL> col segment_name format a30
SQL> col index_name format a30
SQL> select column_name, segment_name, index_name from user_lobs
2 where table_name = 'T_LB'
3 /
COLUMN_NAM SEGMENT_NAME INDEX_NAME
---------- ------------------------------ ------------------------------
Y SYS_LOB0000701495C00002$$ SYS_IL0000701495C00002$$
Z SYS_LOB0000701495C00003$$ SYS_IL0000701495C00003$$
SQL> show parameter recyclebin
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
recyclebin string ON
SQL> drop table t_lb;
SQL> col object_name format a30
SQL> col type format a30
SQL> select object_name, type from recyclebin
2 /
OBJECT_NAME TYPE
------------------------------ ------------------------------
BIN$8hw9X/AeBmngQ0QTGKxsAQ==$0 TABLE
SYS_LOB0000701495C00003$$ LOB
SYS_LOB0000701495C00002$$ LOB
SYS_IL0000701495C00003$$ LOB INDEX
SYS_IL0000701495C00002$$ LOB INDEX
As of constraint/index restoring - you should rename them back:
SQL> create table t (x int, constraint t_pk primary key(x))
2 /
SQL> drop table t;
SQL> select object_name, type from recyclebin;
OBJECT_NAME TYPE
------------------------------ ------------------------------
BIN$8hw9X/AiBmngQ0QTGKxsAQ==$0 TABLE
BIN$8hw9X/AhBmngQ0QTGKxsAQ==$0 INDEX
SQL> flashback table t to before drop;
SQL> select constraint_name, index_name, constraint_type from
2 user_constraints where table_name = 'T';
CONSTRAINT_NAME INDEX_NAME C
------------------------------ ------------------------------ -
BIN$8hw9X/AgBmngQ0QTGKxsAQ==$0 BIN$8hw9X/AhBmngQ0QTGKxsAQ==$0 P
SQL> begin
2 for cur in (select constraint_name, index_name
3 from user_constraints where table_name = 'T'
4 and constraint_type = 'P') loop
5 execute immediate
6 'alter table t rename constraint "'||cur.constraint_name||
7 '" to t_pk';
8 execute immediate
9 'alter index "'||cur.index_name||'" rename to t_pk';
10 end loop;
11 end;
12 /
SQL> select constraint_name, index_name from user_constraints
2 where table_name = 'T';
CONSTRAINT_NAME INDEX_NAME
------------------------------ ------------------------------
T_PK T_PK

Oracle dropping and recreating synonyms

When we use CTAS like this:
create table big2 as select * from big1;
drop table big1;
rename big2 to big1;
If there are synonym existing on big1, do we need to drop synonym on big1 prior to delete and recreate them? Or is this not necessary?
No. Becuase Synonym is just another name you give to an object ( either within your schema or not). See this code below.
(BTW, shouldn't you rename table t2 to t1 directly?? Does your CTAS have other where conditions, which you are not showing here?)
SQL> create table t1 as
2 select * from scott.emp;
Table created.
SQL> select count(*) from t1;
COUNT(*)
----------
14
SQL> select count(*) from t2;
select count(*) from t2
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> create synonym s1 for t1;
Synonym created.
SQL> create table t2 as
2 select * from t1;
Table created.
SQL> drop table t1;
Table dropped.
SQL> alter table t2 rename to t1;
Table altered.
SQL> select count(*) from t1;
COUNT(*)
----------
14
SQL> select count(*) from s1;
COUNT(*)
----------
14

Where can I find the range interval partition tablespaces in the data dictionary?

For a range interval partitioned table, you can specify multiple tablespaces like:
CREATE TABLE range_part_interval_table(col1 NUMBER, col2 NUMBER)
PARTITION BY RANGE (col1)
INTERVAL (10) STORE IN (ts2, ts3, ts4)
(PARTITION VALUES LESS THAN (100) TABLESPACE ts1);
But I can't find where the interval tablespaces are stored in the data dictionary (here, ts2, ts3, ts4). Is this information available somewhere?
This should get you the info you need:
SELECT table_owner, table_name, partition_name, tablespace_name
FROM dba_tab_partitions
WHERE table_name = <table_name>;
The following is the table description:
%> desc dba_tab_partitions
Name Null Type
------------------------------ -------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TABLE_OWNER VARCHAR2(30)
TABLE_NAME VARCHAR2(30)
COMPOSITE VARCHAR2(3)
PARTITION_NAME VARCHAR2(30)
SUBPARTITION_COUNT NUMBER
HIGH_VALUE LONG()
HIGH_VALUE_LENGTH NUMBER
PARTITION_POSITION NUMBER
TABLESPACE_NAME VARCHAR2(30)
PCT_FREE NUMBER
PCT_USED NUMBER
INI_TRANS NUMBER
MAX_TRANS NUMBER
INITIAL_EXTENT NUMBER
NEXT_EXTENT NUMBER
MIN_EXTENT NUMBER
MAX_EXTENT NUMBER
MAX_SIZE NUMBER
PCT_INCREASE NUMBER
FREELISTS NUMBER
FREELIST_GROUPS NUMBER
LOGGING VARCHAR2(7)
COMPRESSION VARCHAR2(8)
COMPRESS_FOR VARCHAR2(18)
NUM_ROWS NUMBER
BLOCKS NUMBER
EMPTY_BLOCKS NUMBER
AVG_SPACE NUMBER
CHAIN_CNT NUMBER
AVG_ROW_LEN NUMBER
SAMPLE_SIZE NUMBER
LAST_ANALYZED DATE
BUFFER_POOL VARCHAR2(7)
GLOBAL_STATS VARCHAR2(3)
USER_STATS VARCHAR2(3)
Your interval partitions don't exist until you have some data in them....
SQL> CREATE TABLE range_part_interval_table(col1 NUMBER, col2 NUMBER)
2 PARTITION BY RANGE (col1)
3 INTERVAL (10) STORE IN (ts2, ts3, ts4)
4 (PARTITION VALUES LESS THAN (100) TABLESPACE ts1);
Table created.
SQL> SELECT table_owner, table_name, partition_name, tablespace_name
2 FROM dba_tab_partitions
3 WHERE table_name = 'RANGE_PART_INTERVAL_TABLE'
4 /
TABLE_OWNER TABLE_NAME PARTITION_NAME TABLESPACE_NAME
----------- ------------------------------ -------------- ---------------
APC RANGE_PART_INTERVAL_TABLE SYS_P55 TS1
SQL>
The empty table has only the defined partition. But if we insert some data for different intervals....
SQL> insert into range_part_interval_table values (90, 8888)
2 /
1 row created.
SQL> insert into range_part_interval_table values (110, 8888)
2 /
1 row created.
SQL> insert into range_part_interval_table values (310, 8888)
2 /
1 row created.
SQL> insert into range_part_interval_table values (120, 8888)
2 /
1 row created.
SQL> SELECT table_owner, table_name, partition_name, tablespace_name
2 FROM dba_tab_partitions
3 WHERE table_name = 'RANGE_PART_INTERVAL_TABLE'
4 /
TABLE_OWNER TABLE_NAME PARTITION_NAME TABLESPACE_NAME
----------- ------------------------------ -------------- ---------------
APC RANGE_PART_INTERVAL_TABLE SYS_P58 TS2
APC RANGE_PART_INTERVAL_TABLE SYS_P55 TS1
APC RANGE_PART_INTERVAL_TABLE SYS_P56 TS4
APC RANGE_PART_INTERVAL_TABLE SYS_P57 TS3
SQL>
check sys.insert_tsn_list$

Resources