oracle 10g foreign key constraints - oracle

ALTER TABLE employees
ADD CONSTRAINT emp_dno_fk FORIEGN KEY(Dno) REFERENCES Departments(Dno);
When I use this command it shows an error like
CONSTRAINT Specification not allowed here.
But when I use this command it works:
ALTER TABLE employees
ADD CONSTRAINT emp_dno_fk Dno REFERENCES Departments(Dno);
Can anyone tell me why Oracle doesn't allow FOREIGN KEY KEYWORD in the first command?

The error message, admittedly, is not very helpful. The following are examples of how a referential integrity constraint may be created in Oracle:
The following examples assume that the column Dno already exists in employees:
ALTER TABLE employees ADD
CONSTRAINT emp_dno_fk FOREIGN KEY (Dno) REFERENCES Departments (Dno);
ALTER TABLE employees ADD
FOREIGN KEY (Dno) REFERENCES Departments (Dno);
The following examples assume that the column Dno does not already exist in employees:
ALTER TABLE employees ADD
CONSTRAINT emp_dno_fk Dno REFERENCES Departments (Dno);
ALTER TABLE employees ADD
Dno REFERENCES Departments (Dno);
Personally, I avoid the syntax versions which add the column and prefer to add it myself.

Related

Creating foreign keys on a table fails in Oracle and 2 schemas

I have two schemas, and I am trying to create a table with two foreign key constraint. Creating the foreign key constraint does not work regardless of whether I add the constraint separately or in the table creation DDL. Also regardless of which of the two users I try to run it.
The oracle error is ORA-01031: insufficient privileges.
The table is created when I omit the foreign key constraints.
Intended result: create a table with two constraints.
CREATE TABLE "XXX_MONITORING"."COMPOSITE_STATUS"
( "COMPOSITE_STATUS_ID" NUMBER,
"COMPOSITE_ID" NUMBER,
"STATUS" CHAR(1),
CONSTRAINT "COMPOSITE_FK" FOREIGN KEY ("COMPOSITE_ID")
REFERENCES "XXX_MONITORING_CONFIGURATION"."COMPOSITE_KPI_COMPONENTS" ("COMPONENT_ID") ON DELETE CASCADE ENABLE,
CONSTRAINT "COMPOSITE_STATUS_FK" FOREIGN KEY ("STATUS")
REFERENCES "XXX_MONITORING_CONFIGURATION"."INDICATION_COLOR" ("INDICATION_COLOR_ID") ON DELETE CASCADE ENABLE
);
The table COMPOSITE_KPI_COMPONENTS and INDICATION_COLOR are in different schema i.e. XXX_MONITORING_CONFIGURATION.
That user must grant REFERENCES on COMPOSITE_KPI_COMPONENTS and INDICATION_COLOR to XXX_MONITORING.
-- Grant statement
grant REFERENCES on COMPOSITE_KPI_COMPONENTS to XXX_MONITORING;
grant REFERENCES on INDICATION_COLOR to XXX_MONITORING;

Is "Constraint" keyword required in Alter table Add [Constraint] syntax?

I came across an example with the following query
ALTER TABLE T ADD UNIQUE(col1)
Normally I would write
ALTER TABLE T ADD CONSTRAINT UNIQUE(col1)
ALTER TABLE T ADD CONSTRAINT UQ_1 UNIQUE(col1)
for unnamed and named constraint.
My question is whether the keyword CONSTRAINT is required ? I could not find reference on this. Can we write
ALTER TABLE T ADD FOREIGN KEY(col1) REFERENCE T1(col2)
ALTER TABLE T ADD PRIMARY KEY(col1)
Yes, we can use:
ALTER TABLE T ADD FOREIGN KEY(col1) REFERENCES T1(col2);
ALTER TABLE T ADD PRIMARY KEY(col1);
LiveDemo
or if you want to name them:
ALTER TABLE T ADD CONSTRAINT fk_T_T1 FOREIGN KEY(col1) REFERENCES T1(col2);
ALTER TABLE T ADD CONSTRAINT pk_T PRIMARY KEY(col1);
ALTER TABLE:
Image from: http://docs.oracle.com/cd/B28359_01/server.111/b28286/img/constraint_clauses.gif
and:
Image from: http://docs.oracle.com/cd/B19306_01/server.102/b14200/img/out_of_line_constraint.gif
As shown in the documentation (link below), the keyword CONSTRAINT is optional:
https://docs.oracle.com/cd/B28359_01/server.111/b28286/clauses002.htm#CJAEDFIB
However, it is required if you want to name your constraint.
The constraint <constraint_name> subclause is not required.

drop foreign key without name Oracle

I want to ask a very basic question here.
We may/may not name a constraint while creating a table or after creating the table.
Suppose I chose not to name the foreign key constraint.
The table is having no records.
Can I delete the foreign key name without naming it.
I know how to get name of foreign key and then delete using it like
alter table my_table drop constraint fk_name;
but I want to delete/drop the foreign key constraint without mentioning its name.
Is there anyway to do it?
but i want to delete/drop the foreign key constraint without mentioning its name.
That's not possible. The dropping a foreign key constraint requires a name. However you can find out the system generated name:
select constraint_name
from user_constraints
where table_name = 'MY_TABLE'
and constraint_type = 'R';
Will show you all foreign keys defined on the table MY_TABLE. Using that statement you can even generate the necessary DDL statement:
select 'alter table "'||table_name||'" drop constraint "'||constraint_name||'";'
from user_constraints
where table_name = 'MY_TABLE'
and constraint_type = 'R';
Save the output of that select into a file and you have the statement(s) to drop all foreign keys from that table.

Oracle Database with very few foreign key constraints

I've just started a new project and I am confronted with a production application Oracle 10g database that has just 3 foreign key constraints. I am not used to seeing databases with no foreign key constraints. I am guessing that there may be some performance/concurrency considerations to not using FKs. The reason is that in the logical database schema the architect has specified all the relationships, but these relationships are not implemented in the database as Foreign Key constraints.
Question: I read that I can define a Foreign Key Constraint with RELY NOVALIDATE that will not impact performance. Is it worth while to define RELY FK constraints on this database just so that the relationship can be easily seen? this application is not built using ORM, is it really worth while to do without foreign keys?
The database is denormalised with example below
Table 1 : FINProduct(ID (number), Description(varchar(5)), FINproductCode(varchar(10))...)
Table 2: FINProductCode(ID (number, FINproductCode(varchar(10)) , LastUpdated(datetime)...)
So instead of having a relationship between Tables 1 and 2 the FINproductCode column is just replicated in table 1.
It's too early to drink but I think i need one!
I would be very wary about assuming that the absence of foreign key constraints was a reasoned response to performance issues. There is an overhead to enforcing a foreign key constraint (particularly where appropriate indexes are missing) but it is incredibly unlikely that your application can validate the constraint more efficiently than Oracle can. So the question really is whether you want the small overhead of foreign key constraints or the near certainty that you will get invalid data inserted into the database. It would be extremely unlikely that this is a trade-off that you want to make-- I've yet to meet a business user that would be happy to capture incorrect and incomprehensible data even if doing so was a bit faster than capturing correct data.
Unless there is substantially more background, I would tend to create all the missing foreign key constraints. Creating RELY NOVALIDATE constraints is possible but it defeats the major benefit of foreign key constraints-- preventing invalid data from entering the database in the first place.
It depends on whether you want to add the FK only for documentation purposes or whether you want to prevent future INSERTs/UPDATEs with an invalid FK value.
If you want it only for documentation purposes, I'd create the FK constraint with RELY NOVALIDATE and DISABLE it afterwards - otherwise, Oracle will check it for future INSERTs / UPDATEs.
However: DON'T DO THIS UNLESS YOU ABSOLUTELY NEED IT!
I agree with Justin Cave: In most cases, you should just add "plain" FK constraints - this way, you can ensure that your existing data is correct.
I would try to create the constraints and report violations into a exception table. Fix the data and enable the constraint.
Create some test data
create table parent (pk integer
,data varchar2(1)
,CONSTRAINT PARENT_PK PRIMARY KEY (PK) ENABLE );
create table child (pk integer
,pk_parent integer
,data varchar2(1)
,CONSTRAINT CHILD_PK PRIMARY KEY (PK) ENABLE );
insert into parent values (1,'a');
insert into parent values (2,'b');
insert into child values (1,1,'a');
insert into child values (2,2,'b');
insert into child values (3,3,'c');
Create a foreign key constraint:
alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk);
SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause: an alter table validating constraint failed because the table has
child records.
*Action: Obvious
Create the foreign key with 'enable novalidate' option
alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk) enable novalidate;
table CHILD altered.
insert into child values (4,4,'c');
SQL Error: ORA-02291: Integriteitsbeperking (ROB.FK_PARENT) is geschonden - bovenliggende sleutel is niet gevonden.
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause: A foreign key value has no matching primary key value.
*Action: Delete the foreign key or add a matching primary key.
No new data violating the FK can be inserted.
Now let's fix the data already in the table that violates the FK constraint
Create an exceptions table and try to enable the constraint:
create table exceptions(row_id rowid,
owner varchar2(30),
table_name varchar2(30),
constraint varchar2(30));
ALTER TABLE child ENABLE constraint fk_parent EXCEPTIONS INTO EXCEPTIONS;
Error report:
SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause: an alter table validating constraint failed because the table has
child records.
*Action: Obvious
Check the exceptions table for problems:
select * from exceptions;
ROW_ID OWNER TABLE_NAME CONSTRAINT
------ ------------------------------ ------------------------------ ------------------------------
AABA78 ROB CHILD FK_PARENT
AAFAAA
Ow9AAC
select * from child where rowid = 'AABA78AAFAAAOw9AAC';
Fix the problem
delete from child where pk = 3;
1 rows deleted.
ALTER TABLE child ENABLE constraint fk_parent EXCEPTIONS INTO EXCEPTIONS;
table CHILD altered.
Constraint enabled and data correct

How to create a Foreign Key with "ON UPDATE CASCADE" on Oracle?

In MS SQL Server it is possible to create a foreign key with ON UPDATE CASCADE option, so whenever you update one of the columns in the primary key, the foreign keys in other tables will also be update by the DBMS.
So, how to do it in Oracle?
Oracle does not allow a Foreign Key constraint with “ON UPDATE CASCADE”.
Here are a couple of options you have.
Create the Foreign Key, and create an “On Update” trigger.
Make use of the package below (needs to be installed in the db).
http://tkyte.blogspot.com/2009/10/httpasktomoraclecomtkyteupdatecascade.html
Let me know if you have additional questions or need more information.
Would a database trigger do the job for you ?
Here is the Oracle doc on the subject of Data Integrity for 11g (just incase you were interested).
You can't use on update cascade, but you can create a trigger that will resolve the issue:
create table tab1(
pk int PRIMARY KEY,
aa int);
create table tab2(
pk int PRIMARY KEY,
tab1_pk int,
FOREIGN KEY(tab1_pk) REFERENCES tab1(pk));
------------------------------------------
create or replace trigger tab1_pkUpdate
after update of pk on tab1
for each row
begin
update tab2 s
set s.tab1_pk = :new.pk
where s.tab1_pk = :old.pk;
end;
/

Resources