Foreign Key Problem in SQL - sql

I just wanna ask coz I created a table with a column with two primary keys as shown below:
CREATE TABLE Parent(
Mother varchar(50) NOT NULL,
Father varchar(50) NOT NULL,
PRIMARY KEY(Mother, Father),
Organization varchar(50) NOT NULL
);
Then I am trying to create another table which will have a foreign key to the table shown above:
CREATE TABLE Child(
Name varchar(50) NOT NULL PRIMARY KEY,
Child_Mother varchar(50) REFERENCES Parent(Mother),
Child_Father varchar(50) REFERENCES Parent(Father),
Sibling varchar(50) NOT NULL
);
So I basically am trying to references two columns on the Child Table to a single column from the Parent table with two primary keys. Is this even possible? Thank you very much! :)
*Sample Tables only. But the actual are similar to this.

You haven't created a "table with a column with two primary keys", you've created one with a single composite primary key.
And what you are doing is indeed possible but not in the way you are doing it.
The problem is that you can have two Parent rows with the same Mother and different Father. But your foreign key relationship on Child_Mother will need a single instance of Mother in the Parent table otherwise it won't know which row it's referring to.
You can either have a combined column in the child which references the conbined primary key as you have it, or you can separate the Parent rows.
By that, I mean a parent table wouldn't normally put two people in a single row, it would normally have one row per person and the child would simply reference two separate rows in the Parent table, one for the mother and one for the father.
In terms of your actual tables:
create table Subject(
Subject_ID varchar(50) NOT NULL,
Subject_Description varchar(50) NOT NULL,
PRIMARY KEY(Subject_ID, Subject_Description),
Subject_SID int references Student(Student_ID),
Unit varchar(50) NOT NULL
)
This is not actually normalised since the subject description almost invariable depends on the subject ID. I think the primary key should probably just be on subject ID. By all means have another index on subject description but it shouldn't be part of the primary key.
I'm still not sure that you understand what I'm saying so I'll try to clarify. The line:
PRIMARY KEY(Subject_ID, Subject_Description)
does not make two primary keys, it makes a single primary key made up of the two columns (id and description). Because of that, it is possible to have two rows with the same ID provided that the description is different.
So a foreign key reference to the ID column is not possible. Let's say you had two rows:
ID Subject Other
-- ------- ---------
7 Maths blah blah
7 Physics yada yada
and then tried to add to the schedule table a row with Schedule_SID set to 7. That will choke because the DBMS wouldn't know which 7 you're referring to. So it shouldn't even let you set up that foreign key constraint because the target column isn't unique.

Try this one -
CREATE TABLE Child(
Name varchar(50) NOT NULL PRIMARY KEY,
Child_Mother varchar(50),
Child_Father varchar(50),
Sibling varchar(50) NOT NULL,
Foreign Key (Child_Mother, Child_Father) references Parent(Mother, Father)
);
Since you are creating a primary key which consists of two columns, you need to refer to them together.
What paxdiablo said is true. You are creating a composite primary key which consists of two columns. I would suggest you to use a Surrogate Primary Key.
Edit
CREATE TABLE Child(
id bigint NOT NULL auto_increment, // an "id" column
Name varchar(50) NOT NULL unique,
age int not null,
primary key (id) // "id" column is being declared as surrogate primary key
);
Second Edit
create table Subject(
id int not null,
Subject_ID varchar(50) NOT NULL,
Subject_Description varchar(50) NOT NULL,
PRIMARY KEY(id),
Subject_SID int references Student(Student_ID),
Unit varchar(50) NOT NULL
);
ALTER TABLE Subject ADD CONSTRAINT subject_unique UNIQUE (Subject_id, Subject_Description);
create table Schedule(
Day_MTWTHF varchar(50) NOT NULL,
TIME_HH varchar(50) NOT NULL,
subject_id int not null, -- my newly added column
Schedule_SID int references Student(Student_ID),
foreign key(subject_id) references Subject(id)
);

I'd say your choice of primary key is poor for the Parent table. It looks like you're using names. What happens if you've got two seperate couples whose names match up? John & Jane Smith with Alice and Bob for children, under your design, would also be the same John & Jane Smith from the next town over who've got Charlie and Dolores for kids, even though in reality they're completely unrelated.
Names are invariably a bad choice for keys, as names can be repeated. Using something guaranteed to be unique, such as an auto-incrementing integer, would be far safer, and would allow you to keep the J&J Smith from Springfield seperate from the J&J Smith from Shelbyville.

Related

How to insert a composite primary key into another table?

I have a composite primary key that I would like to insert into another table.
create table courses_instructors
(
courseID int foreign key references Course(C_ID) not null,
instructorID int foreign key references Instructor(I_ID) not null,
primary key (courseID, instructorID), --coourseID and instructorID combined is the composite PK
courseTerm varchar(50) not null,
courseNumber int not null,
courseLocation varchar(50),
courseTime varchar(50),
courseMaxOccupancy int,
courseSeatAvailable int
)
create table courses_students
(
studentID int foreign key references student(S_ID) not null,
courseID int, -- foreign key -- I want this value to the be value that represents the composite PK from the courses_instructors
primary key(studentID, courseID), -- these 2 fields combined would make the composite PK, but with the courseID value I will be able to identify who is the instructor for a course and the other details from the course_instructor table
courseOutcome varchar(50)
)
All the course come from a course table which only contains the course name and the disciple along with a descrption. The course table has a primary key that identifies each course uniquely.
To refer composit primary key, Courses_Students table should be having both the columns CourseID and InstructorID.
And then
ALTER TABLE Courses_Students
ADD CONSTRAINT FK_Courses_Students
FOREIGN KEY(CourseID, InstructorID) REFERENCES Courses_Instructors(CourseID, InstructorID)
Or the table definitions should look like,
create table courses_instructors
(
courseID int foreign key references Course(C_ID) not null,
instructorID int foreign key references Instructor(I_ID) not null,
primary key (courseID, instructorID), --coourseID and instructorID combined is the composite PK
courseTerm varchar(50) not null,
courseNumber int not null,
courseLocation varchar(50),
courseTime varchar(50),
courseMaxOccupancy int,
courseSeatAvailable int
)
create table courses_students
(
studentID int foreign key references student(S_ID) not null,
courseID int,
instructorId int,
FOREIGN KEY(CourseID, InstructorID) REFERENCES Courses_Instructors(CourseID, InstructorID),
primary key(studentID, courseID, InstructorId),
courseOutcome varchar(50)
)
You can either refer two columns as already mentioned or add a surrogate key such as an identity column or GUID to the primary table and refer with to it - It usually performs better.
The course_instructors table is an intersection table implementing an m-m relationship between, as may be easily guessed, course entities and instructor entities. Almost invariably, I don't add a surrogate key to such a table for the simple reason that such a key would never be used. A typical user has a reference to one entity or the other and wishes to see all the other entities it relates to. Or sometimes the user has references to both entities and wished to get the details of their relationship.
This rule is not without exceptions, however, and your use case is just such an example. The table not just expresses a relationship between two entities but becomes an entity unto itself: a class offering. A student will select a class from a published schedule for the class and day/time desired. This will be identified by a class code number of some sort.
This code is what will be used to register for the desired class. In cases such as these, it makes sense to create a surrogate key for the intersection table -- which then becomes the class code printed in the catalog. Thus you would use this class code to refer to the relationship that defines the class offering and not use the composite key.
It looks like you already have such a composite key: the course_number field. You don't have it defined as unique but doesn't it uniquely identity the combination of course, instructor, location and time that makes up each class offering?

Expecting 1-To-Many however creating 1-1 SQL

I want to create a one to many relationship between two tables but for some reason a one to one relationship is being created.
It's strange because identical code for two other tables in the same DB are creating 1-Many relationships as expected.
Here is my code
CREATE TABLE thing
(
ThingID INT NOT NULL,
Words VARCHAR(50) NOT NULL,
OtherWords INT NOT NULL,
CONSTRAINT pk_TRIPID PRIMARY KEY (ThingID),
)
CREATE TABLE otherthing
(
ThingID INT NOT NULL,
Cost SMALLMONEY NOT NULL,
MoreWords INT NOT NULL,
CONSTRAINT pk_Trip PRIMARY KEY (ThingID),
CONSTRAINT fk_Trip FOREIGN KEY (ThingID) REFERENCES thing(ThingID)
)
Any help you can offer is very appreciated.
Both tables have a primary key of thingid.
This prevents many being inserted in either table. The second table needs the primary key removed and ideally changed to a different primary key so that more than one row matching a given thingid can be inserted into it.

Cannot add foreign key constraint, composite PK and FK

CREATE TABLE HOSPITAL (
HOSP_CODE INT(3) NOT NULL,
HOSP_NAME VARCHAR(15),
HOSP_ADDRESS VARCHAR(15),
HOSP_PHONE VARCHAR(8),
HOSP_SUMBED INT(5),
PRIMARY KEY (HOSP_CODE)
);
CREATE TABLE WARD (
HOSP_CODE INT(3) NOT NULL,
WARD_CODE INT(3) NOT NULL,
WARD_NAME VARCHAR(20),
WARD_SUMBED INT(3),
PRIMARY KEY (HOSP_CODE, WARD_CODE),
FOREIGN KEY (HOSP_CODE) REFERENCES HOSPITAL(HOSP_CODE),
FOREIGN KEY (WARD_CODE) REFERENCES WARD(WARD_CODE)
);
I am trying to apply a constrain of a Primary Key that has 2 columns in it (HOSP_CODE and WARD_CODE) in table WARD and a Foreign Key constraint that is consisted of the two PK stated above.
Writing this code gives me the error stated in the title.
I have searched quite a lot about this error but couldn't find anything.
I understand that if there is a composite PK then the FK that refers to the same keys needs to be composite.
What I don't understand (and probably is the reason I have the error) is how can I assign the FK that refers to WARD_CODE.
Thank you in advance for your help and excuse me if I am unclear with my question.
P.S. I am new to SQL.
P.S2. The reason I need it this way is because of an assignment that a teacher gave us whose description mentions that table WARD should have a composite PK(HOSP_CODE,WARD_CODE) and two FKs for HOSP_CODE and WARD_CODE.
This is a bit long for a comment.
I think you might want three tables: Hospitals, Wards, and HospitalWards.
What you are calling Ward would be HospitalWards. You need a second table with one row per WardCode. I might think that the tables would look something like this:
CREATE TABLE WARDS (
WARD_CODE INT(3) NOT NULL,
WARD_NAME VARCHAR(20),
);
CREATE TABLE HospitalWards (
HOSP_CODE INT(3) NOT NULL,
WARD_CODE INT(3) NOT NULL,
WARD_NUMBED INT(3),
PRIMARY KEY (HOSP_CODE, WARD_CODE),
FOREIGN KEY (HOSP_CODE) REFERENCES HOSPITALS(HOSP_CODE),
FOREIGN KEY (WARD_CODE) REFERENCES WARDS(WARD_CODE)
);
The number of beds would be in the junction table. Many hospitals might have maternity wards, for instance, but each would have a different number of beds.
Note that I tend to name tables in the plural rather than the singular.

SQL Foreign key abrevation

Are these T-SQL declarations equals?
CREATE TABLE Person
(
ID INT PRIMARY KEY,
NAME VARCHAR(60)
)
CREATE TABLE Dog
(
CHIP_ID INT PRIMARY KEY,
OWNER_ID INT REFERENCES Person(ID)
)
and
CREATE TABLE Person
(
ID INT PRIMARY KEY,
NAME VARCHAR(60)
)
CREATE TABLE Dog
(
CHIP_ID INT PRIMARY KEY,
OWNER_ID INT,
FOREIGN KEY(OWNER_ID) REFERENCES Person(ID)
)
I'm talking of course about the foreign key, I'm not sure if I have to specify it is a foreign key or not.
Thank you.
Yes, the DBMS see both as the same. But humans can many times miss important details when the code is cryptic. In fact, my preference is this:
CREATE TABLE Person(
ID INT not null,
Name VARCHAR(60) not null,
constraint PK_Person primary key( ID )
);
CREATE TABLE Dog(
ID INT not null,
OwnerID INT,
constraint PK_Dog primary key( CHIP_ID ),
constraint FK_Dog_Owner foreign key( OWNER_ID ) REFERENCES Person( ID )
);
Using the constraint clause not only defines the primary and foreign keys, but allow us to give them a meaningful name. And the surrogate key of each table should be named "ID". Any foreign keys in other tables will expand that name according to its context (RoleID). As you have in the Dog table with OwnerID. Another table with a FK to the same Person table may name it GroomerID or whatever else shows the role that person plays in the context of the table.
Also, as you can see, I prefer CamelCase with SQL Server, leaving OWNER_ID for Oracle.
Some even go so far as to place either NULL or NOT NULL after each column definition. But I find that adds clutter and doesn't really supply information even a beginning SQL developer doesn't already know. So I only supply NOT NULL when appropriate and let the default carry. Actually, in the later versions of Oracle and SQL Server, the NOT NULL for the primary key field is optional as the primary key is going to be defined as NOT NULL no matter what.
Long ago there seemed to be an informal contest to see who could cram the most operations into the fewest words or even characters. Just stay far away from that kind of thinking. But do make everything you write meaningful.
In general, use every opportunity to add meaningful information to the code. The computer doesn't care. Write to the other developers who will follow you.
Both T-SQL will create the foreign key you need. However, I believe the second approach where the code explicitely states "FOREIGN KEY..." is a good contribution to keep easy-maintenance and clean code for future software engineer understanding.

Foreign key referring to more than one primary key values(from one table) - Oracle SQL PLUS

I am still a beginner in SQL and i'm facing an issue. hope you can help me.
I have a table called Department where it has an attribute DEPARTMENT_NO as its primary key.
CREATE TABLE DEPARTMENT(
DEPARTMENT_NO INT NOT NULL,
NAME VARCHAR(25) NOT NULL,
LOCATION CHAR(15),
PRIMARY KEY(DEPARTMENT_NO));
I have another table called Doctor where it has an attribute DNUM as a foreign key referring to DEPARTMENT_NO :
CREATE TABLE DOCTOR(
DOCTOR_ID CHAR(9) NOT NULL,
DNUM INT NOT NULL,
NAME VARCHAR(20) NOT NULL,
DOB DATE,
SPECIALTY VARCHAR(20) NOT NULL,
SALARY INT,
CITY VARCHAR(15),
STREET VARCHAR(15),
START_DATE DATE,
PRIMARY KEY(DOCTOR_ID))
FOREIGN KEY(DNUM) REFERENCES DEPARTMENT(DEPARTMENT_NO));
A doctor can be working in one or two departments. So, if I have a doctor working in department 1 and 4 (the values for DNUM will include 1 and 4).
I initially chose the data type of DNUM to be INT(same as DEPARTMENT_NO data type). But INT is not ideal for multiple values.
What should the data type be? or what other solution i have if,for example, I run a query for returning the name of the doctors working in department 4.
The query should return all the names of doctors working in department 4(only) and the ones who work in multiple departments(including 4).
Thanks very much in advance and sorry for the long message.
The standard way to represent a "many to many" relationship is via a "junction" (aka "link") table:
CREATE TABLE DOCTOR_DEPARTMENT (
DOCTOR_ID INT REFERENCES DOCTOR(DOCTOR_ID),
DEPARTMENT_NO INT REFERENCES DEPARTMENT (DEPARTMENT_NO),
PRIMARY KEY (DOCTOR_ID, DEPARTMENT_NO)
);
Note the key on {DOCTOR_ID, DEPARTMENT_NO}, which ensures the same doctor cannot be connected to the same department twice.
It also implicitly creates a composite (aka. "concatenated") index on these fields in that order, which makes it very quick to find departments of a given doctor (via an index range scan). If you need to query in the opposite "direction" (for doctors of the given department), flip the order of fields. If you need both queries, then you'll need both indexes (i.e. you'll need to create one index explicitly).
Consider adding ORGANIZATION INDEX clause, if you need just one of these indexes.
You need an additional table called doctor_department
create table doctor_department
(doctor_id integer references doctor(doctor_id) not null,
dnum integer references department(dnum) not null
)
You can create another table with relation to these 2 tables
Say,
Create table Dept_Doctors(
ID int not null,
DOCTOR_ID char(9) not null,
DEPARTMENT_NO INT NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY(DEPARTMENT_NO) REFERENCES DEPARTMENT(DEPARTMENT_NO),
FOREIGN KEY(DOCTOR_ID) REFERENCES DOCTOR(DOCTOR_ID));
You can join the 3 tables and get the desired result.