Add constraint to compare two attributes of different tables? - sql

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)
);

Related

Setting up indexes for multiple foreign keys

An error message regarding indexes displays when foreign keys are added using the following scripts. I have added primary keys and indexes different ways but not sure if the diagram is providing information about how to setup the indexes/primary keys that I'm not seeing.
CREATE TABLE aocommercial_building(
parcel CHAR(25) NOT NULL,
suffix INT NOT NULL,
owner VARCHAR(255) NULL,
owner2 VARCHAR(255) NULL,
);
CREATE TABLE aocommercial_heatcool(
parcel CHAR(25) NOT NULL,
suffix INT NOT NULL,
section INT NULL,
heat_cool_cd VARCHAR(255) NULL
);
CREATE TABLE aocommercial_unit(
parcel CHAR(25) NOT NULL,
suffix INT NOT NULL,
section INT NOT NULL,
occ_desc VARCHAR(255) NULL
);
CREATE TABLE aocom_misc_bldg(
parcel CHAR(25) NOT NULL,
suffix INT NOT NULL,
section INT NOT NULL,
misc_bldg_type VARCHAR(255) NULL
);
ALTER TABLE aocommercial_unit ADD FOREIGN KEY (parcel) REFERENCES aocommercial_building(parcel);
ALTER TABLE aocommercial_unit ADD FOREIGN KEY (suffix) REFERENCES aocommercial_building(suffix);
ALTER TABLE aocommercial_heatcool ADD FOREIGN KEY (parcel) REFERENCES aocommercial_unit(parcel);
ALTER TABLE aocommercial_heatcool ADD FOREIGN KEY (suffix) REFERENCES aocommercial_unit(suffix);
ALTER TABLE aocommercial_heatcool ADD FOREIGN KEY (section) REFERENCES aocommercial_unit(section);
ALTER TABLE aocom_misc_bldg ADD FOREIGN KEY (parcel) REFERENCES aocommercial_unit(parcel);
ALTER TABLE aocom_misc_bldg ADD FOREIGN KEY (suffix) REFERENCES aocommercial_unit(suffix);
ALTER TABLE aocom_misc_bldg ADD FOREIGN KEY (section) REFERENCES aocommercial_unit(section);
enter image description here
For each table, what column (or combination of columns) uniquely identifies each row? Then, include in each CREATE TABLE another line with PRIMARY KEY(...).
For each table, if there is no particular set of columns to uniquely define each row, then add
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id)
Look around; there are lots and lots of examples.

SQL Server : constraints and foreign keys

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
);

Oracle: Many to Many: Requires two Foreign Key Constraints?

Im very new to SQL and i tried to create a many to many relationship:
CREATE TABLE HOUSE_USER
(
USER_ID NUMBER(10) NOT NULL,
USER_EMAIL VARCHAR(255) NOT NULL,
USER_PASSWORD VARCHAR(255) NOT NULL,
CONSTRAINT USER_PK PRIMARY KEY(USER_ID),
CONSTRAINT PROFILE_FK FOREIGN KEY(PROFILE_ID) REFERENCES HOUSE_PROFILE(PROFILE_ID)
);
CREATE TABLE HOUSE_USER_GROUPE
(
USER_GROUPE_ID NUMBER(10) NOT NULL,
USER_GROUPE_NAME VARCHAR(255) NOT NULL,
CONSTRAINT USER_GROUPE_PK PRIMARY KEY(USER_GROUPE_ID)
);
CREATE TABLE HOUSE_USER_USER_GROUPE
(
USER_ID NUMBER(10) NOT NULL,
USER_GROUPE_ID NUMBER(10) NOT NULL,
CONSTRAINT USER_USER_GROUPE_PK PRIMARY KEY(USER_ID, USER_GROUPE_ID),
CONSTRAINT USER_FK FOREIGN KEY(USER_ID) REFERENCES HOUSE_USER(USER_ID),
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES HOUSE_USER_GROUPE(USER_GROUPE_ID)
);
I need to ask now if these two constraints:
CONSTRAINT USER_FK FOREIGN KEY(USER_ID) REFERENCES HOUSE_USER(USER_ID),
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES
are neccessary or not. I ask because i have another many to many relationship:
CREATE TABLE HOUSE_USER_GROUPE
(
USER_GROUPE_ID NUMBER(10) NOT NULL,
USER_GROUPE_NAME VARCHAR(255) NOT NULL,
CONSTRAINT USER_GROUPE_PK PRIMARY KEY(USER_GROUPE_ID)
);
CREATE TABLE HOUSE_ACCESSR
(
ACCESSR_ID NUMBER(10) NOT NULL,
ACCESSR_NAME VARCHAR(255) NOT NULL,
CONSTRAINT ACCESSR_PK PRIMARY KEY(ACCESSR_ID)
);
CREATE TABLE HOUSE_USER_GROUPE_ACCESR
(
USER_GROUPE_ID NUMBER(10) NOT NULL,
ACCESSR_ID NUMBER(10) NOT NULL,
CONSTRAINT USER_GROUPE_ACCESSR_PK PRIMARY KEY(USER_GROUPE_ID, ACCESSR_ID),
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES HOUSE_USER_GROUPE(USER_GROUPE_ID),
CONSTRAINT ACCESSR_FK FOREIGN KEY(ACCESSR_ID) REFERENCES HOUSE_ACCESSR(ACCESSR_ID)
);
I cant create the second many to many table because i already used the constraint:
CONSTRAINT USER_GROUPE_FK FOREIGN KEY(USER_GROUPE_ID) REFERENCES HOUSE_USER_GROUPE(USER_GROUPE_ID),
I could just rename it but because of that error:
ORA-02264: name already used by an existing constraint
I just was wondering if these constraints are mandatory.
Yes, you should create the foreign key constrain on both tables.
The foreign key constraints are there to maintain referential integrity; ensuring that you can't insert values that don't exist in the parent table.
If you don't add the constraint to HOUSE_USER_GROUPE_ACCESR then you don't get that protection in that table. And you should want that protection everywhere.
Your only apparent mistake is that the constraint names are identical to each other. I traditionally either include No Name (letting Oracle decide on the name, because I never refer to the constraint by name) or use a format something like fk_<table>_<field>.
You need to do the constraints.. create the second constraints with another name.

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),
);

Error Defining Foreign Key

I have the following two database tables defined:
CREATE TABLE [dbo].[Classrooms] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[SystemAccount_ID] INT NOT NULL,
[ClassroomName] VARCHAR (30) NOT NULL,
CONSTRAINT [PK_Table] PRIMARY KEY CLUSTERED ([ID]),
CONSTRAINT [FK_Classrooms_SystemAccount] FOREIGN KEY ([SystemAccount_ID]) REFERENCES [dbo].[SystemAccounts] ([ID])
);
CREATE TABLE [dbo].[Students] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[SystemAccount_ID] INT NOT NULL,
[Classroom_ID] INT NULL,
[PhotoID] INT NULL,
[FirstName] VARCHAR (20) NOT NULL,
[LastName] VARCHAR (40) NOT NULL,
[NewsTemplate] TINYINT NOT NULL,
CONSTRAINT [PK_Students] PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_Students_Classrooms] FOREIGN KEY ([Classroom_ID]) REFERENCES [dbo].[Classrooms] ([ID]),
CONSTRAINT [FK_Students_SystemAccounts] FOREIGN KEY ([SystemAccount_ID]) REFERENCES [dbo].[SystemAccounts] ([ID])
);
Data model details:
Students belong to zero or one classroom via Classroom_ID FK
Students belong to one System Account via SystemAccount_ID FK
Classrooms belong to one System Account via SystemAccount_ID FK (implying a system account can have zero or more Classrooms)
What I'm attempting to do is enforce when students are added to a classroom (by setting the Classroom_ID key in the Students table) that the classroom belongs to the same system account as the student. I could easily enforce this at the business logic layer but then I'd be requiring every programmer to remember to do this. So ideally, I'd be able to do this at the data layer as a constraint.
I tried adding a FK constraint to the Students table:
CONSTRAINT [FK_Students_ToTable] FOREIGN KEY ([SystemAccount_ID]) REFERENCES [Classrooms]([SystemAccount_ID])
Which results in the following error compliments of SQL Server:
Update cannot proceed due to validation errors.
Please correct the following errors and try again.
SQL71516 :: The referenced table '[dbo].[Classrooms]' contains no primary or candidate keys that match the referencing column list in the foreign key. If the referenced column is a computed column, it should be persisted.
I've tried a few different things but my SQL mojo isn't powerful enough to hack past this one. Any help would be greatly appreciated.
Add a UNIQUE constraint on the combination of the two columns in Classrooms:
CREATE TABLE [dbo].[Classrooms] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[SystemAccount_ID] INT NOT NULL,
[ClassroomName] VARCHAR (30) NOT NULL,
CONSTRAINT [PK_Table]
PRIMARY KEY CLUSTERED ([ID]),
CONSTRAINT [FK_Classrooms_SystemAccount]
FOREIGN KEY ([SystemAccount_ID])
REFERENCES [dbo].[SystemAccounts] ([ID]),
CONSTRAINT [UQ_Classrooms_ID_SystemAccount_ID]
UNIQUE ([SystemAccount_ID], [ID])
);
Then, in the Students table, combine the two FOREIGN KEY constraints into one, or in your case (because Classroom_ID isnullable), change the FK to Classroom to use the combination of the two columns:
CREATE TABLE [dbo].[Students] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[SystemAccount_ID] INT NOT NULL,
[Classroom_ID] INT NULL,
[PhotoID] INT NULL,
[FirstName] VARCHAR (20) NOT NULL,
[LastName] VARCHAR (40) NOT NULL,
[NewsTemplate] TINYINT NOT NULL,
CONSTRAINT [PK_Students]
PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_Students_Classrooms]
FOREIGN KEY ([SystemAccount_ID], [Classroom_ID])
REFERENCES [dbo].[Classrooms] ([SystemAccount_ID], [ID]),
CONSTRAINT [FK_Students_SystemAccounts] -- this wouldn't be needed if
FOREIGN KEY ([SystemAccount_ID]) -- Classrooms_ID was NOT NULL
REFERENCES [dbo].[SystemAccounts] ([ID])
);