Skip to Main Content
  • Questions
  • Referential integrity and system tables

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question.

Asked: May 23, 2004 - 12:07 am UTC

Last updated: December 12, 2007 - 8:15 am UTC

Version: 10.1.0.2

Viewed 1000+ times

You Asked

Hi Tom

I'd like to get your two cents worth on a debate that is currently raging at a client site.

The point being discussed essentially revolves around referential integrity. Good coding practices generally call for using foreign keys where referential integrity is required. Foreign keys also let the database do what it does best, store data and maintain relationships between data. This general point on database theory is accepted by both sides.

However where the point of contention creeps in is when the "parent" entity in a foreign key relationship is in a system table. A case in point might be your debug.f system, where the controlling table contains a column for an Oracle username.

...
create table debugtab(
userid varchar2(30),
...

The data modellers and developers (from an outsource provider) argue that referential integrity rules should be applied uniformly. Therefore in a case such as this there should be a foreign key created on the debugtab linking back to the sys.users$ table. This would obviously make it impossible to have a user in the debugtab who did not already exist as an Oracle user.

The DBAs and application support team (inhouse) argue that while referential integrity is important and should be used where appropriate, the Oracle system tables are a special case and should never be tinkered with or linked to with foreign keys. The implications of doing so are many and varied, with issues such as application code containing such foreign keys potentially preventing Oracle patches or upgrades from being successfully applied being near the top of the list.

The data modeller guys counter this with the argument that a table is a table, and that foreign keys should be used wherever referential integrity needs to be ensured.

To make a long story shorter, the outsourcer has application code they have developed and supplied to a host of other clients that contain this kind of linking to the sys and/or system tables, and we are the first site they have encountered that won't accept an application containing this kind of code. They don't want to maintain two separate code bases (understandable), but we don't want to worry about an application which potential makes supporting the database harder than it needs to be. The tricky point is our firm has already invested a lot of time and money in to the implementation project, and we are being seen as a road block in the way of rolling out an application that "everybody else already has".

Thanks in advance for your thoughts.

and Tom said...

It is not going to happen.

You cannot even create such an integrity constraint in general. And imagine what would happen if you did so! You would potentionally break the database.

The DBA's and support team know that of which they speak.

The data modeller needs to understand that the data dictionary belongs to Oracle and cannot be touched, not anymore than THEIR model could be touched by some other 3rd party.

I'd be interested, extremely interested in the name of such a product, the vendor and an example of a foreign key they've made (given the data dictionary doesn't have that many primary/unique keys in the first place, none of the core tables do in any event). And even when they do:

sys@ORA9IR2> select * from KOTAD$ where rownum=1
*
ERROR at line 1:
ORA-30732: table contains no user-visible columns


so what? you cannot see anything in them anyhow???





Or better yet, have this outsourcer get in writing from Oracle Support that such a technique is PERMITTED and SUPPORTED.

Rating

  (7 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

FK to sys/system tables. no way.

Shiv, May 24, 2004 - 7:25 am UTC

You are right Tom.
I bet oracle wouldn't support any installation that has referntial intergity with sys or system schema. Other than oracle patches/upgrades I can see likely issues with export/import, transportable tablespaces etc

cheers
Shiv

A reader

A reader, November 15, 2004 - 2:43 am UTC

Is it possible to have Referential integrity between two schemas ?For an example schema A's table refrences schema b's tables and if parent record found then insert otherwise display usual referential integrity error.

Cheers


Tom Kyte
November 15, 2004 - 6:40 am UTC

yes, yes it is.  there is a grant for "references" 


ops$tkyte@ORA9IR2> create table t ( x int );
 
Table created.
 

 
 
ops$tkyte@ORA9IR2> grant references on t to scott;
 
Grant succeeded.
 

A reader, January 27, 2005 - 1:55 pm UTC

I feel (perhaps naively) that it is a good idea to have referential integrity for usernames. For example, our employee table has a username column, whose purpose is to relate employee data to the currently logged in user. When the employee logs into the application, he needs to see which orders have been assigned for him to process today. If an adminstrator makes a typo when entering the username into the employee table, we could run into problems.

I had, in the past, made a materialized view which queries the dba_users view. I gave the MV a primary key, to which the employee table's foreign key pointed. I am now getting the feeling this was not the best idea. Could doing this cause the problems mentioned above (patch problems, export issues, etc.)? Should I abandon my hopes for username referential integrity?

Thank you...


Tom Kyte
January 27, 2005 - 2:13 pm UTC

it would have been OK, technically.  It would not be straight forward, for if you just "did it", you would get:

BEGIN dbms_mview.refresh( 'MV' ); END;
 
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-02266: unique/primary keys in table referenced by enabled foreign keys
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 803
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 860
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 841
ORA-06512: at line 1
 


on the refresh (it tries to truncate and insert /*+append*/, the truncate fails)

you could use a refresh group to work around that.  But they you would get:

 
BEGIN dbms_refresh.refresh('group1'); END;
 
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-02292: integrity constraint (OPS$TKYTE.SYS_C005597) violated - child
record found
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 803
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 860
ORA-06512: at "SYS.DBMS_IREFRESH", line 683
ORA-06512: at "SYS.DBMS_REFRESH", line 195
ORA-06512: at line 1


on the refresh (since it deletes all and then inserts all) -- so you would create the constraint on the child table DEFERRABLE.

Then the refresh would work <b>as long as the child table didn't have any refrencing records!!!!</b>

Which brings us straight back to -- no, it wouldn't be practical -- the refresh would "break" every time you dropped a user but still had them in the child table.


I think the list of users that should be in the child table is in fact an application table -- not a dictionary table -- problem. 

Value based RI

A reader, November 21, 2006 - 5:17 am UTC

Hi Tom,
We have a generic table for our application, with columns as below:
Atrribute_Name
Attribute_Value
....
Based upon attribute_name we have other tables like
TBL_ADDRESS with address_key.......
TBL_ITEM with item_code.....
What we want to achieve with RI as below:
If in attribute table the Atrribute_Name='ADDRESS' then check with TBL_ADDRESS table that attribute_value (in this case - say 123 as address_key) must exist in TBL_ADDRESS table, similarly, if Atrribute_Name='ITEM' then check with TBL_ITEM table, attribute_value (in this case - item_code ) must exist as in TBL_ITEM table
i.e., we want to achieve value based RI.
Any help will be really useful.
btw: We us Oracle 9.2
Regards



Tom Kyte
November 22, 2006 - 3:19 pm UTC

hahahaha, this is too good.

please.

use a real data model and you can have RI.

use this and you get bits and bytes. period.

12g....

A reader, November 23, 2006 - 5:28 am UTC

Hi Tom,
Could be a "wish list" for 12g... :-)
Cheers!

Integrity constraint Error even there is no rows to be deleted

Gopal, December 11, 2007 - 9:57 am UTC

Hi Tom,

Please find the following query.
delete 
from   table1 
where  col1='TEST' 
and    col2 
and not in ( select c1 from tab1
             union all
      select c2 from tab2
      union all
      select c3 from tab3
      )

While executing the above query I receive the error :ORA-02292 integrity constraint (string.string) violated - child record found. As verified with the data manually, the query will delete 0 rows. Even I am getting this integrity constraint error. Please help.

Regards.
Gopal.
Tom Kyte
December 11, 2007 - 11:05 am UTC

not that I don't believe you ....
but....

do this for us:

select * from   table1 
where  col1='TEST' 
and    col2 
and not in ( select c1 from tab1
             union all
         select c2 from tab2
         union all
         select c3 from tab3
         )

Integrity constraint error

Gopal, December 12, 2007 - 2:05 am UTC

Thanks for your response.
As you said, I have executed the below query.
select * 
from   table1 
where  col1='TEST' 
and    col2  not in ( select c1 from tab1
                      union all
                      select c2 from tab2
                      union all
                      select c3 from tab3
                     )

The above query returns no rows.

Sub query: returns 1
select c1 from tab1  // returns 1
union all           
select c2 from tab2  // no rows
union all          
select c3 from tab3  // no rows

But while deleting the values, using the below query, it says integrity constraint(ORA-02292) error.
delete table1 
where  col1='TEST' 
and    col2  not in ( select c1 from tab1
                      union all
                      select c2 from tab2
                      union all
                      select c3 from tab3
                     )

If I substitue the value(1) which is returned be the sub query, it works.
delete table1 
where  col1='TEST' 
and    col2  not in (1)

The table1 has only one row
col1 col2
TEST 1

Please help.

Regards,
Gopal.
Tom Kyte
December 12, 2007 - 8:15 am UTC

give me an example - create tables, inserts to reproduce with.