SQL. How to reference a composite primary key Oracle? - sql

I have two parent tables: Treatment and Visit.
Treatment table:
create table Treatment (
TreatCode CHAR(6) constraint cTreatCodeNN not null,
Name VARCHAR2(20),
constraint cTreatCodePK primary key (TreatCode),
);
Visit table:
create table Visit (
SlotNum NUMBER(2),
DateVisit DATE,
ActualArrivalTime DATE,
constraint cVisitSlotDatePK primary key (SlotNum, DateVisit)
);
Now I try to create a child table:
create table Visit_Treat (
TreatCode constraint cTreatCodeFK references Treatment(TreatCode),
SlotNum constraint cSlotNumFK references Visit(SlotNum),
DateVisit constraint cDateFK references Visit(DateVisit),
constraint cVisitTreatPK primary key (SlotNum, TreatCode, DateVisit)
);
Everything executes fine till the 3 line. Starting from the 3rd line, i.e. SlotNum constraint ... there is a message: no matching unique or primary key. There was already a similar question, but i did not quite get the logic to apply in my case. I reference each column one by one, and it works for the Treatment table parent. How should i correct reference Visit table parent?

CONSTRAINT fk_column
FOREIGN KEY (column1, column2, ... column_n)
REFERENCES parent_table (column1, column2, ... column_n)
in your case
create table Visit_Treat (
TreatCode CHAR(6) constraint cTreatCodeFK references Treatment(TreatCode),
SlotNum NUMBER(2),
DateVisit DATE,
constraint cVisitTreatPK primary key (SlotNum, TreatCode, DateVisit),
constraint fk_slotnumDatevisit FOREIGN KEY(SlotNum,DateVisit)
references Visit(SlotNum,DateVisit)
);

A foreign key must reference the primary key of the parent table - the entire primary key. In your case, the Visit table's primary key is SlotNum, DateVisit but the foreign key from Visit_Treat only references SlotNum.
You have two good options:
Add a DateVisit column to Visit_Treat and have the foreign key be SlotNum, DateVisit, referencing SlotNum, DateVisit in Visit.
Create a non-business primary key on Visit (for example a column named VisitID of type NUMBER, fed by a sequence), add a VisitID column to Visit_Treat, and make that the foreign key.
And two bad options:
Change the Visit primary key to be only SlotNum so your Visit_Treat foreign key will work. This probably isn't what you want.
Don't use a foreign key. I don't recommend this option. If you're having trouble setting up a foreign key that you know should exist, it generally means a design problem.

Related

Create table with foreign key to an other table created below in sql file

My problem is that i have two tables with each table having a foreign key to the other table.
Each time , i execute the SQL file containing the creation of the two tables, it gives me an error that he doesn't find the other table. I'm working with sqlplus to execute the sql file.
Here's an example of SQL file i tried with :
create table A(
Age number(3),
name number(3) constraint A_FK references B(name))
/
create table B(
Age number(3) constraint B_FK references A(Age),
name number(3))
And even if i reverse the order, it gives the same error.
Thanks for help.
This is a problem of cycles in foreign keys. One method is to add all foreign keys after table creation (as I think the other answers propose).
You can also just do that for the first table:
create table A (
Age number(3) primary key,
name number(3)
);
create table B (
name number(3) primary key,
Age number(3),
constraint B_FK foreign key (age) references A(Age)
);
alter table B add constraint A_FK foreign key (name) references B(name);
Here is a db<>fiddle.
Notes:
Foreign keys should reference primary keys, so I added that declaration as well.
I recommend making the primary key the first column in the table.
You can also define the constraint inline for one of the tables (i.e. age number(3) constraint b_fk references a(age)).
The table column(s) that is referred by a foreign key must exist at the time when the constraint is created. Since you have some kind of cyclic reference between the tables, you need to do this in three steps:
first create one table without the foreign key
create the second table (with its foreign key)
finally add the foreign key to the first table with an alter table statement
You also need the referred column to have a unique or primary key constraint set up, otherwise you would get error ORA-02270: no matching unique or primary key for this column-list.
create table A(
age number(3) primary key,
name number(3)
);
create table B(
age number(3) constraint B_FK references A(Age),
name number(3) primary key
);
alter table A add constraint A_FK foreign key (name) references B(name);
Demo on DB Fiddle
Side note: I am quite suspicious about your sample structure, but this could be because your oversimplified it in the question.
It fails because the reference table doesn't exist yet.
Create the tables without the key first. Then drop one and recreated it with the reference. Then drop the 2nd and recreate it with the reference.
Create table first and then ADD the CONSTRAINT
ALTER TABLE A
ADD FOREIGN KEY (name) REFERENCES B(name);
ALTER TABLE B
ADD FOREIGN KEY (age) REFERENCES A(age);

SQL: Primary and foreign key

I am creating a table that has two values that are both primary and foreign at the same time. I do not know how to create them in SQL. Here is what I did but I get the error, there must only be one primary key. what is the correct way?
CREATE TABLE movie_director(
director_id CHAR(8)
constraint pk_director_id_movie_director
PRIMARY KEY
constraint fk_director_id_movie_director
REFERENCES director,
movie_id VARCHAR(30)
constraint pk_movie_id_movie_director
PRIMARY KEY
constraint fk_movie_id_movie_director
REFERENCES movie
)
What you seem to be looking for is a compound primary key. Change your table definition to something like the following:
CREATE TABLE movie_director(
director_id CHAR(8)
constraint fk_director_id_movie_director
REFERENCES director,
movie_id VARCHAR(30)
constraint fk_movie_id_movie_director
REFERENCES movie,
CONSTRAINT PK_MOVIE_DIRECTOR
PRIMARY KEY (DIRECTOR_ID, MOVIE_ID));
Your error seems pretty clear. There can only be one PRIMARY KEY on a table.
You need to create a COMPOUND PRIMARY KEY which consists of two columns (director_id,movie_id).
From wikipedia:
In database design, a compound key is a key that consists of two or more attributes that uniquely identify an entity occurrence.

How to use two columns in a foreign key constraint

I have two tables:
Article
Subscription
In the Article table I have two columns that make up the primary key: id, sl. In the Subscription table I have a foreign key 'idsl`.
I use this constraint :
constraint FK_idsl
foreign key (idsl) references CSS_SubscriptionGroup(id, sl)
But when I run the query, I getting this error:
Number of referencing columns in foreign key differs from number of referenced columns, table X
In Article Table I have two fields that are the primary key: id,sl. In the Subscription Table I have a foreign key 'idsl`
This design is broken - it is apparent that the composite primary key in Article(id, sl) has been mangled into a single compound foreign key in table Subscription. This isn't a good idea.
Instead, you will need to change the design of table Subscription to include separate columns for both id and sl, of the same type as the Article Table, and then create a composite foreign key consisting of both columns, referencing Article in the same order as the primary key, e.g:
CREATE TABLE Article
(
id INT NOT NULL,
sl VARCHAR(50) NOT NULL,
-- Other Columns
CONSTRAINT PK_Article PRIMARY KEY(id, sl) -- composite primary key
);
CREATE TABLE Subscription
(
-- Other columns
id INT NOT NULL, -- Same type as Article.id
sl VARCHAR(50) NOT NULL, -- Same type as Article.sl
CONSTRAINT FK_Subscription_Article FOREIGN KEY(id, sl)
REFERENCES Article(id, sl) -- Same order as Article PK
);
Edit
One thing to consider here is that by convention a column named table.id or table.tableid should be unique, and is the primary key for the table. However, since table Article requires an additional column sl in the primary key, it implies that id isn't unique.
correct syntax for relation:
CONSTRAINT FK_OtherTable_ParentTable
FOREIGN KEY(OrderId, CompanyId) REFERENCES dbo.ParentTable(OrderId, CompanyId)
You must try like this:
constraint FK_idsl foreign key (id,sl) references CSS_SubscriptionGroup(id,sl)

ORA-02270 Referencing a foreign key

I have 1st table:
CREATE TABLE HEAD (
Code int,
Name varchar(99),
HType char(1),
HDate date,
OpBal number(10),
CONSTRAINT pk_head PRIMARY KEY (Code, Name));
and 2nd table:
CREATE TABLE SUBHEAD (
HCode int,
SubCode int,
Name varchar(99),
SDate date,
OpBal number(10),
CONSTRAINT fk_subhead FOREIGN KEY (HCode) REFERENCES HEAD(Code),
CONSTRAINT pk_subhead PRIMARY KEY (Hcode, SubCode));
Now when I run the script, I get:
CONSTRAINT fk_subhead FOREIGN KEY (HCode) REFERENCES HEAD(Code),
ERROR at line 7:
ORA-02256: number of referencing columns must match referenced columns
I have been looking around trying to figure out what's wrong and I think it has something to do with parent table constraint but I am totally stumped on how to fix this.
Your problem is that your foreign key is not referencing the entire primary key from HEAD.
So you either need to change the foreign key (to include name in there) or change the primary key of HEAD to exclude name there.
So either change
CONSTRAINT pk_head PRIMARY KEY (Code, Name));
to
CONSTRAINT pk_head PRIMARY KEY (Code));
or change
CONSTRAINT fk_subhead FOREIGN KEY (HCode) REFERENCES HEAD(Code)
to
CONSTRAINT fk_subhead FOREIGN KEY (HCode, Name) REFERENCES HEAD(Code, Name)

Oracle composite primary key / foreign key question

I have a composite primary key in 1 table in oracle. I want to create a foreign key for one table entry in my second table that references the composite primary key in the first table. I am getting the error ORA-02256. Any thoughts on how I can enter this?
CREATE TABLE groupspersonx (
personid number,
groupid number,
CONSTRAINT pk_persongroupid PRIMARY KEY(personid, groupid)
);
CREATE TABLE restrictedgroups (
groupid number,
name varchar2(50),
dateadded date,
since date,
notes varchar2(1024),
CONSTRAINT pk_groupid PRIMARY KEY(groupid),
CONSTRAINT fk_persongroup FOREIGN KEY(groupid) REFERENCES groupspersonx(personid, groupid)
);
The error is because the FOREIGN KEY is one column, but you're trying to supply two columns as the parent. There's no need to tie to the composite key, because the restrictedgroups doesn't have a personid column...
You also have the relationship backwards - use:
CREATE TABLE restrictedgroups (
groupid number,
name varchar2(50),
dateadded date,
since date,
notes varchar2(1024),
CONSTRAINT pk_groupid PRIMARY KEY(groupid)
);
CREATE TABLE groupspersonx (
personid number,
groupid number,
CONSTRAINT pk_persongroupid PRIMARY KEY(personid, groupid),
CONSTRAINT fk_persongroup FOREIGN KEY(groupid) REFERENCES restrictedgroups(groupid)
);
I would add a foreign key constraint for whatever table the personid would be coming from.
CREATE TABLE groupspersonx(
personid number, groupid number,
CONSTRAINT pk_persongroupid PRIMARY KEY(personid, groupid));
CREATE TABLE restrictedgroups (
pid number,
groupid number,
name varchar2(50),
dateadded date,
since date,
notes varchar2(1024),
CONSTRAINT pk_groupid PRIMARY KEY(groupid),
CONSTRAINT fk_persongroup FOREIGN KEY(pid,groupid) REFERENCES groupspersonx(personid, groupid));
* number of references columns is equals with foreign key columns
Whenever you want to create a composite primary key or unique constraint on a column, you can't give reference in another table.
for ex.
sql>create table t1( a number,b number,c number ,primary key(a,b,c));
table created.
sql>create table g1(a number constraint con_fg references t1(a));
ERROR at line 1:
ORA-02270: no matching unique or primary key for this column-list
Here t1 is parent table and g1 is child table. The child table can contains duplicate values in one column. So oracle will not allow that table of column.
See also
SQL>select constraint_name,constraint_type from user_constraints where table_name='T1';
CONSTRAINT_NAME C
------------------------------ -
SYS_C005822 P
So, here also the only constraint for all three columns i.e a,b,c in t1 table.
That's why you can't create a foreign on composite primary key or composite unique constraint
You can't use:
CONSTRAINT fk_persongroup FOREIGN KEY(groupid) REFERENCES groupspersonx(personid, groupid)
Change that too:
CONSTRAINT fk_persongroup FOREIGN KEY(groupid) REFERENCES groupspersonx(groupid)
That should work.