LAST_DDL_TIME for GLOBAL TEMPORARY TABLE -- Oracle 11g bug? - oracle

When I create a GLOBAL TEMPORARY TABLE in Oracle 11g (11.2.0.1.0), and then add a new column to it, Oracle does not update the LAST_DDL_TIME column of the system catalog views (e.g. DBA_OBJECTS):
create global temporary table test# (foo varchar2(3));
select last_ddl_time from dba_objects where object_name='TEST#';
-- Shows created time
-- Wait a minute
alter table test# add (bar varchar(3));
select last_ddl_time from dba_objects where object_name='TEST#';
-- Shows NO UPDATE
-- Wait a minute
alter table test# drop (bar);
select last_ddl_time from dba_objects where object_name='TEST#';
-- Shows time when column was dropped
However, when I execute the same sequence of SQL statements in Oracle 12c (12.1.0.2.0), then LAST_DDL_TIME does reflect newly-added columns.
create global temporary table test# (foo varchar2(3));
select last_ddl_time from dba_objects where object_name='TEST#';
-- Shows created time
-- Wait a minute
alter table test# add (bar varchar(3));
select last_ddl_time from dba_objects where object_name='TEST#';
-- Shows time when column was added
-- Wait a minute
alter table test# drop (bar);
select last_ddl_time from dba_objects where object_name='TEST#';
-- Shows time when column was dropped
This behavior appears to be very specific to adding columns to GLOBAL TEMPORARY TABLES, and to Oracle 11g; renaming or dropping columns does affect LAST_DDL_TIME as expected.
Is this a known Oracle 11g bug?! If so, is there an official Oracle patch update for it?

Related

ORA-14450 GTT alter table issue

Iam facing a issue while altering the GTT table.
I need to find the active users on that table, Can someone help in query regarding how to find the active users on the specific object in oracle database
As far as I can tell, you didn't explain what problem you're trying to solve, but rather what you think that might help you solve it. So, let me try to guess.
Here's a global temporary table (GTT):
SQL> create global temporary table gtt (id number) on commit preserve rows;
Table created.
SQL> insert into gtt values (1);
1 row created.
SQL> commit;
Commit complete.
You're trying to alter it, but - it fails:
SQL> alter table gtt add name varchar2(10);
alter table gtt add name varchar2(10)
*
ERROR at line 1:
ORA-14450: attempt to access a transactional temp table already in use
OK, so - delete row(s) and commit, then try again:
SQL> delete from gtt;
1 row deleted.
SQL> commit;
Commit complete.
SQL> alter table gtt add name varchar2(10);
alter table gtt add name varchar2(10)
*
ERROR at line 1:
ORA-14450: attempt to access a transactional temp table already in use
Still no luck. But, if you truncate the table, then it works:
SQL> truncate table gtt;
Table truncated.
SQL> alter table gtt add name varchar2(10);
Table altered.
SQL>
If that's not what you're after, then see if this answers your question: connect as a privileged user (such as SYS, if you don't have any other) and run such a query: it shows who owns the GTT, its name, who locked it (which Oracle user) and which operating system user is it (that might help you to contact those people):
SQL> select b.owner,
2 b.object_name,
3 a.oracle_username,
4 a.os_user_name
5 from v$locked_object a, dba_objects b
6 where a.object_id = b.object_id;
OWNER OBJECT_NAM ORACLE_USERNAME OS_USER_NAME
--------------- ---------- --------------- ------------------------------
SCOTT GTT SCOTT littlefoot
SQL>

Oracle : table always "exist" after drop table

I'm using Oracle and I have a strange thing.
I dropped a table using :
drop table t_my_table, and committed.
But when I launch select * from t_my_table, it shows the data, as if the table is not dropped.
I tried disconnecting and reconnecting, it stills shows the data when I select.
And when I once again try with :
drop table t_my_table, it tells me that this table does not exist.
But if I run select again, the data is always there.
How is this possible ?
Thank you.
You mean this case?
create view t_my_table as
select 'I''m here' as txt from dual;
drop table t_my_table;
ORA-00942: table or view does not exist
But
select * from t_my_table;
TXT
--------
I'm here
solution of the most probably cause
select OBJECT_TYPE from user_objects where object_name = 'T_MY_TABLE';
OBJECT_TYPE
-------------------
VIEW
You defined a view (or other object type other than TABLE), that can't be dropped with DROP TABLE, but can be selected.
Simple check in USER_OBJECTS the OBJECT_TYPE. You may alternatively see also SYNONYM as proposed in other answer.
Note that it is not a MATERIALIZED VIEW as if you try to drop a Materialized View with DROP TABLE a different error message is raised:
ORA-12083: must use DROP MATERIALIZED VIEW to drop T_MY_TABLE
What does this return?
select * from all_synonyms
where synonym_name = 'T_MY_TABLE';
I suspect there is a synonym T_MY_TABLE that points to a table in a different schema.
drop table t_my_table purge;
Specify PURGE if you want to drop the table and release the space associated with it in a single step. If you specify PURGE, then the database does not place the table and its dependent objects into the recycle bin.
...
Using this clause is equivalent to first dropping the table and then purging it from the recycle bin. This clause lets you save one step in the process. It also provides enhanced security if you want to prevent sensitive material from appearing in the recycle bin.
Probably something different is happening.
Normal case would be:
SQL> create table t1 as select 1 a from dual;
Table T1 created.
SQL> drop table t1;
Table T1 dropped.
SQL> select * from t1;
Error starting at line : 22 in command -
select * from t1
Error at Command Line : 22 Column : 20
Error report -
SQL Error: ORA-00942: table or view does not exist
00942. 00000 - "table or view does not exist"
*Cause:
*Action:
So what was the message after the drop table?
Is t_my_table really a table?
Try select * from all_objects where lower(object_name) = 't_my_table'

"table definition changed" despite restore point creation after table create/alter

FLASHBACK TABLE to a restore point fails when that restore point was created immediately after a table change. The below code only works if there is a sleep between certain steps.
SQL> DROP TABLE TEST_TABLE;
Table dropped.
SQL> CREATE TABLE TEST_TABLE AS SELECT 1 A FROM DUAL;
Table created.
SQL> ALTER TABLE TEST_TABLE ENABLE ROW MOVEMENT;
Table altered.
SQL> --Sleep required here to prevent error on flashback.
SQL> DROP RESTORE POINT TEST_RESTORE_POINT;
Restore point dropped.
SQL> CREATE RESTORE POINT TEST_RESTORE_POINT;
Restore point created.
SQL> FLASHBACK TABLE TEST_TABLE TO RESTORE POINT TEST_RESTORE_POINT;
FLASHBACK TABLE TEST_TABLE TO RESTORE POINT TEST_RESTORE_POINT
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed
Why is a delay required and is there a way to eliminate it?
This oddity might be caused by SMON process which is responsible to keep track between SCNs and timestamps which flashback query relies upon. There is a mapping table SYS.SMON_SCN_TIME where every 5 minutes a new record is inserted SMON.
Internally during the FLASHBACK TABLE executes a command INSERT /*+ APPEND */ into SYS_TEMP_FBT SELECT /*+ FBTSCAN FULL(S) PARALLEL(S, DEFAULT) */ :1, :2, :3, rowid, SYS_FBT_INSDEL FROM "<schema>."TEST_TABLE" as of SCN :4 S (notice a table SYS_TEMP_FBT is created in the same schema) which uses this mapping.
Up to Oracle 10.2 you needed to wait up to whole 5 minutes to succeed with FLASHBACK query on a new/altered object. In 11.1 the TIM_SCN_MAP column was introduced to make the mapping more fine grained. Maximum of 100 mappings is stored in one value which makes roughly 3 seconds precision in timestamp to SCN mapping.
I tried many things but I don't think you can do anything about it but wait around 3 seconds to avoid the error because this is handled asynchronously by background process without any user control.

oracle database to find recently added column in table or database(oracle)

I want to find the recently added column to existing table.
How to find recently added column in table or database(oracle).
Recently the table and the databases of our web application got modified and some of the table got altered.
Ideally you should have restricted access to your Production database, together with a build process which applies scripts out of source control, rather than allowing people to change things using TOAD. It's pretty hard to conduct forensics in a free-fire zone.
You can find out which tables have changed by interrogating the data dictionary:
SQL> select object_name from user_objects t
2 where t.object_type = 'TABLE'
3 and t.last_ddl_time > trunc(sysdate)
4 /
no rows selected
SQL> alter table t23 add col_3 number
2 /
Table altered.
SQL> select object_name from user_objects t
2 where t.object_type = 'TABLE'
3 and t.last_ddl_time > trunc(sysdate)
4 /
OBJECT_NAME
----------------------------------------------------------
T23
SQL>
This won't tell you what the change was, or who did it. To get better information you need a proper audit trail. At the very least you should enable auditing of DDL statements....
SQL> audit ALTER TABLE;
Audit succeeded.
SQL>
Find out more.

oracle database AUDIT doesn't show SQL text and bind values

Based on this tutorial I have configured auditing on a database with these options:
AUDIT ALL BY db BY ACCESS;
AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE, DELETE TABLE BY db BY ACCESS;
AUDIT EXECUTE PROCEDURE BY db BY ACCESS;
I prepare query from java and run a SELECT query. DBA_AUDIT_TRAIL table shows my SELECT query but SQL_TEXT and SQL_BIND fields are empty. How can I see them? Should I enable any other option? I'm using Oracle 11.2 Express Edition. Is this because It is express edition?
The column SQLTEXT and SQLBIND are populated only when AUDIT_TRAIL option is set to db, extended. Here is an example:
SQL> alter system set audit_trail=db,extended scope=spfile;
System altered
Restart the instance.
SQL> audit select on your_table;
Audit succeeded
SQL> select sqltext from sys.aud$ where obj$name = 'YOUR_TABLE';
SQLTEXT
--------------------------------------------------------------------------------
null
SQL> select count(*) from your_table;
COUNT(*)
----------
3
SQL> select sqltext from sys.aud$ where obj$name = 'YOUR_TABLE';
SQLTEXT
--------------------------------------------------------------------------------
select count(*) from your_table
SQL>

Resources