SQL Server : constraints and foreign keys - sql

I have an assignment where I must
Create an Entity Relationship diagram of a particular situation, and
Write up the SQL code to represent the diagram
I am new to SQL Server, but I have a table class that has a primary key CRN varchar(10)(UNN) and two foreign keys, emp_id varchar(20) (NN) which has a 1 mandatory relationship with instructor, and room_number varchar(5) (UNN) which also has a 1 mandatory relationship with Classroom.
My code for table Class:
CREATE TABLE class
(
CRN varchar(10) UNSIGNED NOT NULL,
emp_id varchar(20),
room_number varchar(5),
enrollment smallint UNSIGNED NOT NULL,
CONSTRAINT pk_class PRIMARY KEY (CRN),
CONSTRAINT fk_class
FOREIGN KEY (emp_id) REFERENCES instructor (emp_id),
CONSTRAINT fk_class
FOREIGN KEY (room_number) REFERENCES classroom (room_number)
);
The error I'm getting is:
Constraint "FK_CLASS" already exists; SQL statement:
CREATE TABLE class
(CRN varchar(10) UNSIGNED NOT NULL,
emp_id varchar(20),
room_number varchar(5),
enrollment smallint UNSIGNED NOT NULL,
CONSTRAINT pk_class PRIMARY KEY (CRN),
CONSTRAINT fk_class FOREIGN KEY (emp_id) REFERENCES instructor (emp_id),
CONSTRAINT fk_class FOREIGN KEY (room_number) REFERENCES classroom (room_number) ) [90045-193]
I have seen many different examples on how to make a table have two foreign keys, but have had no luck. What am I doing wrong?

Contraints must have a unique name, and you are using name fk_class twice. So naming the one fk_instructor and the other fk_classroom should solve the problem.
Note that there is a shorter notation, which avoids such issues:
CREATE TABLE class (
CRN varchar(10) PRIMARY KEY,
emp_id varchar(20) references instructor (emp_id),
room_number varchar(5) REFERENCES classroom (room_number),
enrollment smallint UNSIGNED NOT NULL
);

Related

Add constraints for a foreign key that references multipleprimary keys from different tables in SQL Plus?

I'm a beginner learning SQL and am having trouble implementing this concept.
Suppose you create the following three tables:
CREATE TABLE dogOwner(
ownerNo VARCHAR(8) CONSTRAINT ownerNo_pk1 PRIMARY KEY,
ownerName VARCHAR(10)
);
CREATE TABLE catOwner(
ownerNo VARCHAR(8) CONSTRAINT ownerNo_pk2 PRIMARY KEY,
ownerName VARCHAR(10)
);
CREATE TABLE petsAdopted(
petNo VARCHAR(8) CONSTRAINT petNo_pk PRIMARY KEY,
ownerNo VARCHAR(8) CONSTRAINT ownerNo_fk1 REFERENCES dogOwner(ownerNo)
CONSTRAINT ownerNo_fk2 REFERENCES catOwner(ownerNo)
);
How do you properly create constraints for the foreign key ownerNo, which references ownerNo from two other tables?
You can't. You could have 2 columns in petsAdopted: dogOwnerNo and catOwnerNo and 2 foreign keys. But the table design doesn't seem to make sense: surely a pet either is a dog or a cat (or something else) regardless of who owns it?
Here is an alternative design:
CREATE TABLE owner(
ownerNo VARCHAR(8) CONSTRAINT ownerNo_pk2 PRIMARY KEY,
ownerName VARCHAR(10)
);
CREATE TABLE petsAdopted(
petNo VARCHAR(8) CONSTRAINT petNo_pk PRIMARY KEY,
petType VARCHAR2(10) NOT NULL CONSTRAINT petTypeChk (CHECK petType in ('CAT','DOG'))
ownerNo VARCHAR(8) CONSTRAINT ownerNo_fk REFERENCES owner(ownerNo)
);
This only address syntax part of your answer which You have got lot of syntax error, but this will not work, Please rethink your design.
CREATE TABLE dogOwner(
ownerNo VARCHAR(8) CONSTRAINT ownerNo_pk1 PRIMARY KEY,
ownerName VARCHAR(10)
);
CREATE TABLE catOwner(
ownerNo VARCHAR(8),
ownerName VARCHAR(10),
CONSTRAINT ownerNo_pk2 PRIMARY KEY (ownerNo),
CONSTRAINT ownerNo_fk1 FOREIGN KEY (ownerNo) REFERENCES dogOwner(ownerNo)
);
CREATE TABLE petsAdopted(
petNo VARCHAR(8) ,
ownerNo VARCHAR(8),
CONSTRAINT petNo_pk PRIMARY KEY (petNo),
CONSTRAINT ownerNo_fk_pet1 FOREIGN KEY (ownerNo) REFERENCES dogOwner(ownerNo),
CONSTRAINT ownerNo_fk_pet2 FOREIGN KEY (ownerNo) REFERENCES catOwner(ownerNo)
);

Add constraint to compare two attributes of different tables?

Here are my tables. I need to check that the 'program' attribute referenced in StudentsBranch with the table Students and the table Branches is the same. How can I do it?
CREATE TABLE Programmes (
name VARCHAR(200) UNIQUE NOT NULL,
CONSTRAINT pk_Programmes PRIMARY KEY (name)
);
CREATE TABLE Students (
id NUMERIC(10,0) UNIQUE NOT NULL,
program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Students PRIMARY KEY (idnr),
FOREIGN KEY (program) REFERENCES Programmes(name)
);
CREATE TABLE Branches (
name VARCHAR(200) UNIQUE NOT NULL,
program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Branches PRIMARY KEY (name, program),
FOREIGN KEY (program) REFERENCES Programmes(name)
);
CREATE TABLE StudentsBranch (
student NUMERIC(10,0) NOT NULL,
program VARCHAR(200) NOT NULL,
branch VARCHAR(200) NOT NULL,
CONSTRAINT pk_StudentsBranch PRIMARY KEY (student),
/* Below how the foreign keys I think should be */
FOREIGN KEY (student, program) REFERENCES Students(idnr, program),
FOREIGN KEY (branch, program) REFERENCES Branches(name, program)
/* I need to add a constraint to verify that the 'program' in Students
* and the 'program' in Branches are equivalent. How?
*/
);
You can't write that constraint with that existing database model you have now.
The only way I see you could do it, is by changing the primary key of Students to (id, program):
CREATE TABLE Students (
id NUMERIC(10,0) UNIQUE NOT NULL,
program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Students PRIMARY KEY (id, program),
FOREIGN KEY (program) REFERENCES Programmes(name)
);
Then the table StudentsBranch could naturally enforce both FKs with using the single column program, as in:
CREATE TABLE StudentsBranch (
student NUMERIC(10,0) NOT NULL,
program VARCHAR(200) NOT NULL,
branch VARCHAR(200) NOT NULL,
CONSTRAINT pk_StudentsBranch PRIMARY KEY (student),
FOREIGN KEY (student, program) REFERENCES Students (id, program),
FOREIGN KEY (branch, program) REFERENCES Branches (name, program)
);
It is always a good idea to have an numeric column of primary key and have primary key for every table.
Once you have primary key for every table you can referece primary key of a specific table and refere it as foerign key.
CREATE TABLE Programmes (
ID INT,
name VARCHAR(200) UNIQUE NOT NULL,
CONSTRAINT pk_Programmes PRIMARY KEY (ID)
);
CREATE TABLE Students(
id INT,
ProgrammID INT NOT NULL,
CONSTRAINT pk_Students PRIMARY KEY (ID),
FOREIGN KEY (ProgrammID) REFERENCES Programmes(ID)
);
CREATE TABLE Branches (
BranchID INT,
ProgrammID INT NOT NULL,
name VARCHAR(200) UNIQUE NOT NULL,
--program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Branches PRIMARY KEY (BranchID, ProgrammID),
FOREIGN KEY (ProgrammID) REFERENCES Programmes(ID)
);
CREATE TABLE StudentsBranch (
StudentsBranchID INT,
studentID INT NOT NULL,
ProgrammID INT NOT NULL,
BranchID INT NOT NULL,
CONSTRAINT pk_StudentsBranch PRIMARY KEY (StudentsBranchID),
FOREIGN KEY (ProgrammID) REFERENCES Programmes(id),
FOREIGN KEY (studentID) REFERENCES Students(id),
FOREIGN KEY (BranchID, ProgrammID) REFERENCES Branches(BranchID, ProgrammID)
);

Translate the schema provided in into an “equivalent” relational schema (tables) in SQL

Person(p#,name,birthdate,nationality,gender)
Actor(p#,aguild#)
FK (p#) refs Person
Director(p#,dguild#)
FK (p#) refs Person
Writer(p#, wguild#)
FK (p#) refs Person
Studio(name)
ScreenPlay(title,year)
Authored(title,year,writer)
FK (title, year) refs ScreenPlay
FK (writer) refs Writer (p#)
Movie(title,studio,year,genre,director,length)
FK (studio) refs Studio (name)
FK (title, year) refs ScreenPlay
FK (director) refs Director (p#)
Cast(title,studio,year,role,actor,minutes)
FK (title, studio, year) refs Movie
FK (actor) refs Actor (p#)
Affiliated(director,studio)
FK (director) refs Director (p#)
FK (studio) refs Studio (name)
I am unable to make the table for the author, I get an error saying "does not conform to the description
of the parent key of table or nickname"
CREATE TABLE person (
p# int,
name varchar(255),
birthdate DATE,
nationality varchar(255),
gender varchar(255),
constraint person_pk
primary key (p#)
);
CREATE TABLE actor (
p# int,
aguild varchar(255),
constraint actor_pk   
primary key (p#),
constraint actor_fk_person
foreign key (p#) references person
);
CREATE TABLE director (
p# int,
dguild varchar(255),
constraint director_pk   
primary key (p#),
constraint director_fk_person
foreign key (p#) references person
);
CREATE TABLE writer (
p# int,
wguild varchar(255),
constraint writer_pk   
primary key (p#),
constraint writer_fk_person
foreign key (p#) references person
);
CREATE TABLE studio (
name varchar(255) not null,
constraint studio_pk   
primary key (name)
);
CREATE TABLE screenplay (
title varchar(255) not null,
year varchar(255) not null,
constraint screenplay_pk   
primary key (title, year)
);
CREATE TABLE authored (
title varchar(255) not null,
year varchar(255) not null,
writer varchar(255) not null,
constraint authored_pk
primary key (title,year,writer),
constraint authored_fk_titleyear
foreign key (title, year) references screenplay,
constraint authored_fk_writer
foreign key (writer) references writer (p#) on delete no action
);
CREATE TABLE movie (
title varchar(255) not null,
studio varchar(255) not null,
year varchar(255) not null,
genre varchar(255),
director varchar(255),
length varchar(255),
constraint movie_pk   
primary key (title, studio, year),
constraint movie_fk_studio
foreign key (studio) references studio(name),
constraint movie_fk_titleyear
foreign key (title, year) references screenplay,
constraint movie_director
foreign key (director) references director(p#)
);
CREATE TABLE cast (
title varchar(255) not null,
studio varchar(255) not null,
year varchar(255) not null,
role varchar(255) not null,
actor varchar(255) not null,
minutes varchar(255),
constraint cast_pk   
primary key (title, studio, year, role, actor),
constraint cast_fk_titlestudioyear
foreign key (title, studio, year) references movie,
constraint cast_fk_actor
foreign key (actor) references actor(p#)
);
CREATE TABLE affiliated (
director varchar(255) not null,
studio varchar(255) not null,
constraint affiliated_pk   
primary key (director, studio),
constraint affiliated_fk_director
foreign key (director) references director(p#)
constraint affiliated_fk_studio
foreign key (studio) references studio(name)
);
You have several elementary mistakes. You appear to be learning, so take the time to study basic rules of RDBMS and data modelling/normalisation.
It's unwise to use column names with special characters like # because it will give maintenance and usability issues. You are using "p#" to indicate a primary key that is a surrogate, but that is unwise, consider using a naming convention instead for column-names of surrogate key. For example : person_pk, actor_pk, director_pk, writer_pk.
Some of your tables use surrogate keys (p#) while others use natural keys(example studio.name). If you use natural-keys that are long (example varchar(255)), then child tables that use those natural-keys will use much more space and searches will be less efficient than if you use a surrogate key of type integer or bigint for the pk.
Next if you want a column to act as a primary key then it must be NOT NULL. some of your tables break this rule so will fail to create.
When you have a foreign key, its column(s) datatype(s) must match that of the relevant parent table column(s). Your example breaks that rule so you will get syntax errors.
authored_fk_writer needs to reference a key of writers but you have omitted any key field, and the relevant foreign key column is varchar(255) which does not correspond to the primary key of writer (which is int).
For some of your compound foreign keys that use natural-keys, the compound length exceeds documented limits. Consider normalising your model to use correct datatypes for the foreign key columns (i.e. don't duplicate the natural key in the child table, but instead use the surrogate key column of the parent table).
The clause 'references writer ()' is not correct in DB2. You must either not specify any columns including parentheses (the parent table must have PK in this case), or specify the corresponding columns of the parent table explicitly inside the parentheses (the parent table must have PK or Unique Constraint on them).
Check the REFERENCES clause syntax of the CREATE TABLE statement.

Foreign key on a Foreign key - SQL Server

I'm creating a database for a project in which I need to declare a foreign key on another foreign key for the sake of a checking constraint.
I have a Person table and a Groups table, both of these contain a DepartmentID. Whenever I insert a new task in the Task table, I want to check that the Groups.DepartmentID matches the Person.DepartmentID.
The idea is that a task is linked to a person and has 2 types, a grouptype which defines if its database work, financial work etc and a tasktype which defines if its maintenance, training etc. When a person tries to add a task with a groupType that is not for his/her department it should fail.
I tried adding these attributes to the Task table as a foreign key, however declaring a foreign key on a non-unique or non-primary key isn't accepted in Microsoft SQL Server (the DepartmentID in the Person and Group tables cannot be unique!).
Anyone knows how to fix this?
CREATE TABLE Department
(
ID int PRIMARY KEY IDENTITY,
Name varchar(50),
UNIQUE ("Name")
)
CREATE TABLE Groups
(
ID int IDENTITY,
GroupType varchar(50) PRIMARY KEY,
Description varchar(255) DEFAULT ('-'),
DepartmentID int
FOREIGN KEY (DepartmentID) REFERENCES Department(ID),
)
CREATE TABLE Person
(
ID int PRIMARY KEY IDENTITY,
Name varchar(50),
DepartmentID int
FOREIGN KEY (DepartmentID) REFERENCES Department(ID)
)
CREATE TABLE TaskType
(
ID int IDENTITY,
TaskType varchar(50) PRIMARY KEY,
Description varchar(255) DEFAULT ('-'),
)
CREATE TABLE Task
(
ID int IDENTITY,
TimeFrame decimal(4,2),
Yearcount int,
GroupType varchar(50),
TaskType varchar(50),
WeekNr int,
ExceptionDetail varchar(255) DEFAULT ('-'),
PersonID int
)
These are the FK attributes in the task table that are not accepted:
GDID int FOREIGN KEY REFERENCES Groups(DepartmentID),
PDID int FOREIGN KEY REFERENCES Person(DepartmentID),
CHECK (GDID = PDID),
UNIQUE ("TaskType", "GroupType", "WeekNr", "Yearcount"),
FOREIGN KEY (TaskType) REFERENCES TaskType(TaskType),
FOREIGN KEY (PersonID) REFERENCES Person(ID),
FOREIGN KEY (GroupType) REFERENCES Groups(GroupType)
Add wider "super keys" to these tables that include the primary key and additional columns1, then declare the foreign keys using them. Whether you also remove the superfluous smaller foreign keys is a matter of taste:
CREATE TABLE Groups(
ID int IDENTITY,
GroupType varchar(50) PRIMARY KEY,
Description varchar(255) DEFAULT ('-'),
DepartmentID int FOREIGN KEY (DepartmentID) REFERENCES Department(ID),
constraint Group_Dep_XRef UNIQUE (GroupType,DepartmentID)
)
CREATE TABLE Person(
ID int PRIMARY KEY IDENTITY,
Name varchar(50),
DepartmentID int FOREIGN KEY (DepartmentID) REFERENCES Department(ID),
constraint Person_Dept_XRef UNIQUE (ID,DepartmentID)
)
CREATE TABLE Task(
ID int IDENTITY,
TimeFrame decimal(4,2),
Yearcount int,
GroupType varchar(50),
TaskType varchar(50),
WeekNr int,
ExceptionDetail varchar(255) DEFAULT ('-'),
PersonID int,
DepartmentID int,
constraint FK_Group_Dept_XRef FOREIGN KEY (GroupType,DepartmentID)
references Group (GroupType,DepartmentID),
constraint FK_Person_Dept_XRef FOREIGN KEY (PersonID,DepartmentID)
references Person (ID,DepartmentID),
UNIQUE ("TaskType", "GroupType", "WeekNr", "Yearcount"),
FOREIGN KEY (TaskType) REFERENCES TaskType(TaskType),
FOREIGN KEY (PersonID) REFERENCES Person(ID), --Redundant now
FOREIGN KEY (GroupType) REFERENCES Groups(GroupType) --Also redundant
)
(I also consolidated GDID and PDID into DepartmentID - if they're always meant to be equal, why store that twice and then have to have another constraint to assert their equality?)
1If a primary key (or unique key) is sufficient to uniquely identify each row then any wider key which includes the key columns and additional columns must also be sufficient to uniquely identify each row.

Error There are no primary or candidate keys in the referenced table

I'm getting this error when trying to create a table with foreign key:
There are no primary or candidate keys in the referenced table 'TeamToPlayers' that match the referencing column list in the foreign key 'FKey2'.
I don't understand why, there is a primary key in the table TeamToPlayers.
Here are the queries:
create table TeamToPlayers
(TeamName varchar(50) NOT NULL,
PlayerName varchar(50) NOT NULL,
primary key(TeamName,PlayerName),
CONSTRAINT FKey FOREIGN KEY (TeamName) REFERENCES Teams(TeamName)
)
create table Players
(PlayerName varchar(50) NOT NULL,
primary key(PlayerName),
CONSTRAINT FKey2 FOREIGN KEY (PlayerName) REFERENCES TeamToPlayers(PlayerName)
);
Table TeamToPlayers primary key consists of two fields - you must reference both as otherwise it's not a key. I think you may have your key the wrong way round - it should be on TeamToPlayers and referencing Players like so:
create table TeamToPlayers
(
TeamName varchar(50) NOT NULL,
PlayerName varchar(50) NOT NULL,
primary key(TeamName,PlayerName),
CONSTRAINT FKey FOREIGN KEY (TeamName) REFERENCES Teams(TeamName),
CONSTRAINT FKey2 FOREIGN KEY (PlayerName) REFERENCES Players(PlayerName)
)
create table Players
(PlayerName varchar(50) NOT NULL,
primary key(PlayerName),
);