does foreign key always reference to a unique key in another table? - oracle

Is it not possible that foreign key(single column) in a child table references to a parent key which has some duplicate values?

By the SQL standard, a foreign key must reference either the primary key or a unique key of the parent table. If the primary key has multiple columns, the foreign key must have the same number and order of columns. Therefore the foreign key references a unique row in the parent table; there can be no duplicates.
Re your comment:
If T.A is a primary key, then no you can't have any duplicates. Any primary key must be unique and non-null. Therefore if the child table has a foreign key referencing the parent's primary key, it must match a non-null, unique value, and therefore references exactly one row in the parent table. In this case you can't make a child row that references multiple parent rows.
You can create a child row whose foreign key column is NULL, in which case it references no row in the parent table.

No, it is not possible.
When you define a foreign key constraint on a table, it means there is only one corresponding key on the foreign table. If multiples existed on the foreign table which one would be meant?
Wikipedia has this definition on the Foreign key entry:
A foreign key is a field in a relational table that matches a candidate key of another table
Candidate keys are unique within a table.

Yes, it is possible for a foreign key to reference a column with duplicate values.
This can happen if the primary key uses a non-unique index and is not validated when it is created. (But I have never seen a situation like this in real life. As #Bill Karwin pointed out, it would be very confusing. So this may not be a situation you really need to worry about.)
--Create a table with two duplicate rows
create table test1(a number);
insert into test1 values(1);
insert into test1 values(1);
commit;
--Create a non-unique index
create index test1_index on test1(a);
--Use the non-unique index for the primary key, do not validate
alter table test1 add constraint test1_pk primary key (a)
using index test1_index novalidate;
--Build another table with a foreign key to TABLE1
create table test2(a number,
constraint test2_fk foreign key (a) references test1(a));
--Inserting a value that refers to the duplicate value still works.
insert into test2 values(1);
commit;
--The foreign key still works:
--ORA-02291: integrity constraint (TEST2_FK) violated - parent key not found
insert into test2 values(2);
--The primary key works as expected, but only for new values:
--ORA-00001: unique constraint (TEST1_PK) violated
insert into test1 values(1);

Related

In which order should we apply primary key, foreign key constraints and create index if the Oracle table has data?

1.In which order should we apply primary key, foreign key constraints and create index if the Oracle table has millions of data and does not have prior constraints?
2.Can we use 'NOLOGGING PARALLEL' while applying primary key and foreign key constraints like we do while applying(creating) indexes? Or any other method so that primary key and foreign key constraints could be applied faster?
Note: I'll use bullets so that it is easier to read, as it is easy to get lost in long sentences.
My thoughts on the subject; see if anything of this helps.
Well,
as you can't create a foreign key constraint if column(s) it references aren't part of primary or unique key
you'll obviously first have to create primary key constraints
and then foreign key constraints
When you
create a primary key constraint,
Oracle automatically creates index that supports it, unless there's already an index you can use (with the USING INDEX clause)
which means that you can "skip" some indexes (those for primary key constraints as they'll already exist) and virtually save some time
and create "other" indexes
On the other hand,
if you first create unique index on future primary key columns and
later add primary key constraint with the USING INDEX clause, Oracle will "skip" check for possible duplicate values because unique index won't allow them
The same goes for
NOT NULL constraint on future primary key columns; primary key doesn't allow NULLs so - if a column already is NOT NULL, enforcing primary key constraint can skip NULL check as well
I don't know
which columns you'll additionally index, but - as you're on Oracle 11g -
don't forget to index all foreign key constraint columns
because you might encounter unexpected table locks if you
update primary key column in parent table, or
delete parent record
Can you do it with no logging and in parallel? Yes:
SQL> create table test (id number, name varchar2(20));
Table created.
SQL> create unique index ui1_test_id on test (id) nologging parallel 20;
Index created.
SQL> alter table test add constraint pk_test primary key (id) using index ui1_test_id nologging parallel 20;
Table altered.
SQL>
But you'll probably want to change the index and table back to NOPARALLEL and LOGGING when the initial creation is done.
SQL> alter index ui1_test_id noparallel;
Index altered.
SQL> alter table test logging noparallel;
Table altered.

creating composite foreign key from two different tables primary keys in oracle

table1:
tid(primary key) // no foreign keys here
table2:
sid(primary key) // no foreign keys here too
table3:
Tid
Sid
iid(primary key)
foreign key(Tid,Sid) references table1(tid).table2(sid)
In table3 i want to make a composite foreign key or composite foreign key constraint but failed . there are many questions related to this .But none of them seems helpful to me . How can i do that ? Is it valid ? Then what is the syntax of making composite foreign key from two different tables primary key
It's not possible to have a single foreign key referencing fields on different tables, and it makes no sense at all. A foreign key of two or more fields implies that the combination of values of the fields must be match on a single record of the referenced table, and this can't be done if the referenced fields are on different tables.
What you can do is to create two distinct foreing keys to the two tables, as following:
CREATE TABLE table3(
iid NUMBER,
Tid NUMBER,
Sid NUMBER,
CONSTRAINT pk PRIMARY KEY (iid) USING INDEX TABLESPACE idx,
CONSTRAINT fk001 FOREIGN KEY (tid) REFERENCES table1(tid),
CONSTRAINT fk002 FOREIGN KEY (sid) REFERENCES table2(sid)
);

Not able to add a new column to the existing primary key

I have a primary key PK1 for the table TABLE1. Need to add one more column to the existing primary key.
I was tying the following alter script
ALTER TABLE TABLE1
ADD CONSTRAINT "PRIMARYKEYS" PRIMARY KEY
("PK1",
"PK2");
Error report:
SQL Error: ORA-02260: table can have only one primary key
02260. 00000 - "table can have only one primary key"
*Cause: Self-evident.
*Action: Remove the extra primary key.
How can I add one more column to the primary key, without affecting the data(data has been verified , there are no duplication.)
If you have concern about new data that violates PK can be added during the time interval when the old PK dropped, but the new one is not created, you can create a unique index first :
CREATE UNIQUE INDEX IDXU_TABLE1_PK ON TABLE1(PK1,PK2);
ALTER TABLE TABLE1 DROP CONSTRAINT [old_pk_constraint_name] ;
ALTER TABLE TABLE1 ADD CONSTRAINT "PRIMARYKEYS" PRIMARY KEY
(PK1,PK2) USING INDEX IDXU_TABLE1_PK;
Another option is to keep index associated with the old PK constraint until new PK is created :
ALTER TABLE TABLE1 DROP CONSTRAINT [old_pk_constraint_name] KEEP INDEX;
ALTER TABLE TABLE1 ADD CONSTRAINT "PRIMARYKEYS" PRIMARY KEY
(PK1,PK2) ;
DROP INDEX [name of unique index associated with the old PK constraint];
You need to drop old primary key first.

FK on a single column referencing a column from composite PK

Not able to create /find the logic to apply FK on a column in child table referencing a column from composite PK of parent table.
create table product(prod_id number,
prod_name varchar2(20),
price number,
constraint PK12 primary key(prod_id,prod_name));
Table created.
create table purchase(prod_id number,
purchase_price number,
constraint FK12 foreign key(prod_id) references product(prod_id));
create table purchase(prod_id number,
purchase_price number,
constraint FK12 foreign key(prod_id) references product(prod_id))
ERROR at line 1:
ORA-02270: no matching unique or primary key for this column-list
Kinldy suggest how i can incorporate this logic.
Thanks.
You can't.
As the error says there's no matching primary key for that column list; you must have one. You have three options:
Remove PROD_NAME from the primary key of PRODUCT. On the face of it this seems like the logical solution, if this is not required in order to make the primary key unique.
Add PROD_NAME to the PURCHASE table.
Create a unique index on PURCHASE.PROD_ID. This seems excessive if it would be a primary key candidate anyway.
I suspect that this is not unique to Oracle. Considering you have a composite primary key in the referenced table, that implies that only one of the columns comprising the composite key is not enough to uniquely identify the record in that table. Therefore, it's impossible to reference only a single column of the primary key in a foreign key relationship that's one-to-many (e.g. one record in the referenced table can have many records in the referencing table--the one with the FK). However, if the relationship to be established is many-to-many, this may be possible.
HTH.

update primary key in oracle

i have table. which has 5 columns in that 3 of the columns makes primary key combinations.
table (cola, colb, colc, cold, cole)
i want to update one of the column which is in primary key group. how to do that?
its giving primary key constraint error.
You should disable do your modification an re enable the constraints that are linked to your primary key. (Unique, non-null, etc...)
Take a look at this website
If you really need to maintain uniqueness over these three columns, then define a unique constraint on the three columns making up your current PK, and then define a new surrogate primary key column.
Just in case you have to change the referncing data too.
First note contrary to MS-SQL-Server there is no foreign Key contraint with on update cascade see How to create a Foreign Key with “ON UPDATE CASCADE” on Oracle?.
Than I would insert a new row in the primary table, update the referencing table to reference the new row and finally delete the original primary row.

Resources