How to insert a composite primary key into another table? - sql

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?

Related

Foreign key to assotiation table

Is it OK to use a reference to a many-to-many association table or explicit FK's are better?
Let's assume we have some many-to-many model like this:
CREATE TABLE Project (
id int NOT NULL,
....
PRIMARY KEY(id)
);
CREATE TABLE Programmer (
id int NOT NULL,
....
PRIMARY KEY(id)
);
CREATE TABLE Project_Programmer_Association(
id int NOT NULL,
project_id int,
programmer_id int,
.... (probably some other data)
FOREIGN KEY (project_id) REFERENCES Project (id),
FOREIGN KEY (programmer_id) REFERENCES Programmer(id)
);
CREATE TABLE Task (
id int NOT NULL,
project_programmer_id int,
....
PRIMARY KEY(id),
FOREIGN KEY (project_programmer_id) REFERENCES Project_Programmer_Association(id)
);
Within Project and Programmer table there are some data, required for the Task, so I need references to both tables. My question is: Should I use this reference in Task
CREATE TABLE Task (
id int NOT NULL,
project_programmer_id int,
....
PRIMARY KEY(id),
FOREIGN KEY (project_programmer_id) REFERENCES Project_Programmer_Association(id)
);
or two explicit keys will be better (exept of additional join absence)
CREATE TABLE Task (
id int NOT NULL,
project_id int,
programmer_id int,
....
PRIMARY KEY(id),
FOREIGN KEY (project_id) REFERENCES Project (id),
FOREIGN KEY (programmer_id) REFERENCES Programmer(id)
);
I would prefer the following schema:
CREATE TABLE Project (
id int NOT NULL,
....
PRIMARY KEY(id)
);
CREATE TABLE Programmer (
id int NOT NULL,
....
PRIMARY KEY(id)
);
CREATE TABLE Project_Programmer_Association(
project_id int,
programmer_id int,
PRIMARY KEY(project_id, programmer_id),
FOREIGN KEY (project_id) REFERENCES Project,
FOREIGN KEY (programmer_id) REFERENCES Programmer
);
CREATE TABLE Task (
id int NOT NULL,
project_id int,
programmer_id int,
PRIMARY KEY(id),
FOREIGN KEY (project_id, programmer_id) REFERENCES Project_Programmer_Association
);
since it has the following advantages: no unnecessary key for Project_Programmer_Association, referential integrity guaranteed for Task; the possibility of joining directly Tasks with Project_Programmer_Association, Project and Programmer. Note that in the case for which there is only a task for each couple programmer-project (and only in that case) than you can remove also the id of Task and make the primary key the other two attributes.
The right question isn't "which is better", but "which represents your data".
If Project_Programmer_Association doesn't hold any data of its own, it may be redundant to keep it, and you could get away with foreign keys to the project and the programmer.
If it could hold data, and more specifically, if a project and a programmer can have several associations (e.g., Bob is the lead developer in project X but just a consultant in project Y), you most definitely need a foreign key to the association itself in order to properly represent your data model.

How to create zero or one to many relationship using sql

I have this data model generated by EntityFramework in an existing application but i want to create the same tables with the same relationships in my database.
I succeeded creating the relationship (one to zero or one) between Student and StudentAddress with the following query which is correct:
CREATE TABLE Student(
StudentId INT NOT NULL PRIMARY KEY,
FirstName VARCHAR(30),
LastName VARCHAR(30),
City VARCHAR(30),
State1 VARCHAR(30),
StandardId INT NOT NULL FOREIGN KEY REFERENCES Standard(StandardId));
CREATE TABLE StudentAddress(
StudentId INT,
Adress1 VARCHAR(30),
Adress2 VARCHAR(30),
City VARCHAR(30),
State VARCHAR(30),
CONSTRAINT StudentAdress_PK PRIMARY KEY(StudentId),
CONSTRAINT StudentAdress_Student_FK FOREIGN KEY(StudentId)
REFERENCES Student(StudentId));
My question is considering this data model how to create the relationship (zero or one to many) between Standard and Student tables.
Thank you for your help
You do this the same way that you implemented the one to zero or one relationship.
So far you have a foreign key in StudentAddress to Student. There is nothing enforcing one address per student. (You could do so with a unique index on `StudentAddress.StudentId'.)
So do the same thing. Have a StandardId field in the Student table, and you will have a many Student to zero or one Standard relationship.
You need a third table that stores the relationships:
CREATE TABLE StandardStudenRelation (
ID INT IDENTITY(1,1) PRIMARY KEY
, StandardID INT NOT NULL
, StudentID INT NOT NULL
, CONSTRAINT Student_ID_FK FOREIGN KEY(StudentId)
REFERENCES Standard(StudentId)
, CONSTRAINT Standard_ID_FK FOREIGN KEY(StandardID)
REFERENCES Standard(StandardId)
);

SQL: Foreign key references a composite primary key

I'm new to SQL and there are a lot of things going on that I still don't seem to quite understand. I have the following table
CREATE TABLE Person
(
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
PRIMARY KEY (First_Name, Name, Address)
);
I know want to create another table that has the primary key from the table Person as foreign key and also as primary key:
CREATE TABLE Purchase
(
No_Installments int,
Rate int,
Person varchar(50) NOT NULL PRIMARY KEY,
CONSTRAINT PFK
FOREIGN KEY (Person) REFERENCES Person (First_Name, Name, Address)
);
For some reason this doesn't work and I get an error every time. I've already looked up the other threads here on stackoverflow, but they don't really seem to help me. What am I doing wrong?
If you have a compound PK made up from three columns, then any child table that wants to establish a foreign key relationship must ALSO have all those 3 columns and use all 3 columns to establish the FK relationship.
FK-PK relationship is an all or nothing proposal - you cannot reference only parts of a primary key - either you reference all columns - or you don't reference.
CREATE TABLE Purchase
(
No_Installments int,
Rate int,
Person varchar(50) NOT NULL PRIMARY KEY,
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
CONSTRAINT PFK
FOREIGN KEY (First_Name, Name, Address)
REFERENCES Person (First_Name, Name, Address)
);
Have an integer primary key, using identity, auto_increment, serial or whatever for your database:
CREATE TABLE Person (
PersonId int identity PRIMARY KEY
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
CONSTRAINT unq_person_3 UNIQUE (First_Name, Name, Address)
);
Then use the identity column for the reference:
CREATE TABLE Purchase (
PurchaseId int identity PRIMARY KEY,
No_Installments int,
Rate int,
PersonId int,
CONSTRAINT PFK
FOREIGN KEY (PersonId) REFERENCES Person (PersonId)
);
Notes:
You really don't want to have to deal with a composite primary key. Have you thought about what the joins will look like?
You don't want a primary key where the values are subject to change. What happens when someone changes his/her name? When someone moves?
Person should not be the primary key in Purchases. Are you only allowing someone to make one purchase?
As noted initially, how you generate such a column varies by database; identity happens to be the way that SQL Server does this.
You probably want to assign a unique ID to each person, not relying on their name to be unique or for an address to be required. That ID will be your Primary key and foreign key. Your purchase table should also have its own id for its primary key -- otherwise because primary keys must be unique, each person can only have one purchase.
CREATE TABLE Person (
id serial NOT NULL,
First_Name varchar(20) NOT NULL,
Name varchar(20) NOT NULL,
Address varchar(50) NOT NULL,
PRIMARY KEY (id));
CREATE TABLE Purchase (
id serial NOT NULL,
No_Installments int,
Rate int,
Person int NOT NULL,
FOREIGN KEY (Person) REFERENCES Person (id),
PRIMARY KEY (id));

how to add constraint with columns in external tables

An easy way to explain my problem is this:
I want to create a table that will contain the information about the subjects that will be dictated in a school. The columns must be:
create table program( teacher varchar(20) references teachers(name),
classroom varchar(20) references classrooms(id),
dtime datetime)
In each one of the tables teachers and classrooms exists a column named 'subject', corresponding to the subject that is dictated by a teacher and the subject that is taught in a classroom (imagine there's no more columns in those tables).
Now, I want to create a constraint in the program table that doesn't let me insert a row where the subject dictated in the classroom is different from the subject dictated by the teacher.
You want to use composite foreign keys. This is going to be simplest by putting the subjectId in the programs table. Here is the example for teachers:
create table teachers (
teacherid int identity(1, 1) primary key,
name varchar(255) not null,
subjectid int references subjects(subjectid),
unique (teacherid, subjectid)
);
create table programs (
programid int identity(1, 1) primary key,
teacherid int references teachers(teacherid),
classroomid int references classrooms(classroomid),
dtime datetime
subjectid int references subjects(subjectid),
foreign key (teacherid, subjectid) references teachers(teacherid, subjectid),
foreign key (classroomid, subjectid) references classrooms(classroomid, subjecdtid)
);
If you don't put the subject in the programs table, then you will need to use a user defined function for the constraint. This seems like a simpler solution.

What exactly does primary key mean in sql

I created a table like this:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (P_Id)
)
but I can't understand the purpose of the primary key
PRIMARY KEY (P_Id)
in that table.
From MSDN:
A table typically has a column or combination of columns that contain
values that uniquely identify each row in the table. This column, or
columns, is called the primary key (PK) of the table and enforces the
entity integrity of the table. You can create a primary key by
defining a PRIMARY KEY constraint when you create or modify a table.