Getting ORA-01403 in dba_segments query during a trigger
JP KrepsAug 20 2009 — edited Aug 20 2009Hi, Everyone --
I need to set up a process which will automatically start Oracle auditing on a table when it's created on a particular tablespace.
I've created an "after create on database" DDL trigger which will fire when (ORA_DICT_OBJ_TYPE = 'TABLE').
In this trigger, I use the DBMS_STANDARD package trigger attribute functions in a query against the dba_segments view to check if the new
table has been created in the targeted tablespace. Here' the query:
SELECT DISTINCT s.tablespace_name
INTO tablespace_name
FROM sys.dba_segments s
WHERE s.owner = ORA_DICT_OBJ_OWNER
AND s.segment_name = ORA_DICT_OBJ_NAME
AND s.segment_type IN ('TABLE', 'TABLE PARTITION')
AND s.tablespace_name = target_tablespace_name;
The only purpose of this query is to make sure that that table is contained in the targeted tablespace identified by the "target_tablespace_name" constant variable used in the WHERE clause. If the query runs without error, then my trigger creates a DBMS_SCHEDULER job that executes an "audit" command to start Oracle auditing on the new table.
To test the trigger, within the trigger code, I put the query inside a PL/SQL block with a "WHEN OTHERS" exception clause that will send formatted error detail to the alert log. Then I successfully create a test table on the targeted tablespace. The trigger fires, but the output shows that the query in my trigger failed with an "ORA-01403: no data found" error, indicating that the dba_segments view contains no records showing that the new table is on the targeted tablespace.
But when, in an already opened PL/SQL session, I immediately run the same query (with the appropriate literals in place of the trigger attribute functions) then the query works with the name of the tablespace returned as expected!
I tried an experiment with the trigger running the same query against the dba_tables view instead of the dba_segments view. It worked without error. The only problem is that if your create a partitioned table, the "tablespace_name" column in the dba_table view is NULL (which makes sense when the various table partitions can be contained in different tablepsaces). So, unfortunately, in the case of creating partitioned tables, the purpose of the query would be defeated.
Why does the trigger work when it queries the dba_tables view, but fails when it queries the dba_segments view? Is there a timing issue which causes a lag between the time the table is created and the time that the dba_segments view is updated? Would the trigger fire inside this time lag, thus causing the dba_segments query to fail? Or is there another explanation?
Thanks in advance for any advice you can give me!