Extra entries in recycle bin when table dropped - oracle

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

Related

How to rename index which is another tablespace 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>

Update second column

I have a table "TEST_TABLE" with two columns TABLE_NAME and RECORD_COUNT.
enter image description here
We want to update the column RECORD_COUNT by taking the total records in table specified in TABLE_NAME.
You could do this with dynamic SQL but why be complicated?
Create a view
Create view my_tables as
Select
'table_1' as "table name",
count(*) as "rows"
From table_1
Add the following for each table
Union all
Select 'table_2',count(*) From table_2
You can then use the view like a table:
Select * from my_tables;
OK, but - why wouldn't you use information Oracle already provides for you? You should regularly gather statistics anyway, so:
SQL> execute dbms_stats.gather_schema_stats(ownname => 'SCOTT', estimate_percent => null);
PL/SQL procedure successfully completed.
and then fetch num_rows from user_tables:
SQL> select table_name, num_rows from user_tables where rownum <= 10;
TABLE_NAME NUM_ROWS
-------------------- ----------
EMP 14
DEPT 4
BONUS 0
SALGRADE 5
DUMMY 1
TBL_ERROR 1
AUDIT_TAB 2
SOURCE_DET 3
EXAMPLE 1
FLIGHT 0
10 rows selected.
SQL>
It can't be much worse than your attempt (due to possible frequent changes to tables' contents; inserts and deletes) because you'd collect your own data periodically (how often?) anyway.
If it has to be your way, then you'd use dynamic SQL, looping through all tables in your schema and actually count number of rows:
SQL> create table test_table
2 (table_name varchar2(30),
3 num_rows number);
Table created.
SQL> create or replace procedure p_test as
2 l_cnt number;
3 begin
4 execute immediate 'truncate table test_table';
5 for cur_R in (select table_name from user_tables) loop
6 execute immediate 'select count(*) from ' ||cur_R.table_name into l_Cnt;
7 insert into test_table (table_name, num_rows) values (cur_r.table_name, l_cnt);
8 end loop;
9 end;
10 /
Procedure created.
Running the procedure and viewing the result:
SQL> exec p_test;
PL/SQL procedure successfully completed.
SQL> select * From test_Table where rownum <= 10;
TABLE_NAME NUM_ROWS
-------------------- ----------
EMP 14
DEPT 4
BONUS 0
SALGRADE 5
DUMMY 1
TBL_ERROR 1
AUDIT_TAB 2
SOURCE_DET 3
EXAMPLE 1
FLIGHT 0
10 rows selected.
SQL>
Note that performance will suffer as number of tables and number of rows stored in them grows.
If I were you, I'd go for the first option.

How to use a variable to alter a constraint of a table in PL SQL?

I am trying to get the name of a constraint and then alter a table to remove the constraint. The constraint has not been named so I guess I have no other option. Here is what I tried:
DECLARE
the_variable VARCHAR2(20);
BEGIN
SELECT CONSTRAINT_NAME INTO the_variable
FROM all_constraints
WHERE table_name = 'MY_TABLE'
AND SEARCH_CONDITION_VC = 'format IN (''CSV'', ''PDF'')';
END;
The query above seems to work fine, but when I try to alter the table in this way:
ALTER TABLE SOME_TABLE DROP CONSTRAINT the_variable;
I get this error:
SQL Error [6550] [65000]: ORA-06550: line 14, column 1:
PLS-00103: Encountered the symbol "ALTER"
You can't perform DDL like that; has to be dynamic SQL. Here's an example - you need what's written in line #9:
SQL> create table my_table (id number primary key);
Table created.
SQL> declare
2 the_variable varchar2(30);
3 begin
4 select constraint_name
5 into the_variable
6 from all_constraints
7 where table_name = 'MY_TABLE';
8
9 execute immediate 'alter table my_table drop constraint ' || the_variable;
10 end;
11 /
PL/SQL procedure successfully completed.
SQL> select count(*) from all_constraints where table_name = 'MY_TABLE';
COUNT(*)
----------
0
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.

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