The INSERT statement conflicted with the FOREIGN KEY constraint on my VB.net - sql

so i was working on my project then i was trying to insert some values that are foreign keys
The INSERT statement conflicted with the FOREIGN KEY constraint
"SCHEDFK4". The conflict occurred in database "EnrollmentDatabase",
table "dbo.tblSubject", column 'Subject_ID'.
Here are my SQL entities
CREATE TABLE tblGradeLevel
(
Grade_ID VARCHAR (5) NOT NULL,
Grade_Name VARCHAR (20) NULL,
PRIMARY KEY (Grade_ID)
)
CREATE TABLE tblSubject
(
Subject_ID VARCHAR (5)NOT NULL,
Subject_Name VARCHAR (20) NOT NULL,
Subject_Desc VARCHAR (20) NOT NULL,
Grade_Name VARCHAR (5) NOT NULL,
PRIMARY KEY (Subject_ID),
CONSTRAINT SUBFK1 FOREIGN KEY (Grade_ID)
REFERENCES tblGradeLevel (Grade_ID)
)
CREATE TABLE tblSchedule
(
Subject_Schedule_ID VARCHAR (5)NOT NULL,
Section_ID VARCHAR (5)NOT NULL,
Teacher_ID VARCHAR (5)NOT NULL,
Time_In VARCHAR (20)NOT NULL,
Time_Out VARCHAR (20)NOT NULL,
Subject_ID VARCHAR (5)NOT NULL,
Grade_ID VARCHAR (5)NOT NULL,
PRIMARY KEY (Subject_Schedule_ID),
CONSTRAINT SCHEDFK1 FOREIGN KEY (Student_ID)
REFERENCES tblStudent_Information (Student_ID),
CONSTRAINT SCHEDFK2 FOREIGN KEY (Section_ID)
REFERENCES tblSection (Section_ID),
CONSTRAINT SCHEDFK3 FOREIGN KEY (Teacher_ID)
REFERENCES tblTeacher (Teacher_ID),
CONSTRAINT SCHEDFK4 FOREIGN KEY (Subject_ID)
REFERENCES tblSubject (Subject_ID),
CONSTRAINT SCHEDFK5 FOREIGN KEY (Grade_ID)
REFERENCES tblGradeLevel (Grade_ID)
)

This is very easy to understand from your error that you are trying to insert a record in tblSchedule but corresponding Subject_ID is missing in tblsubject table.
You have two options to fix this problem.
Drop the foreign key constraint.
Insert into tblsubject an entry which you need to refer in tblSchedule table.
You can read more about Foreign Key Constraints at MSDN link here.

To avoid this error from happening, make sure that the value you are inserting into a column that references another table exists in that table. If the value does not exist in the primary table, insert to that table first before doing the insert on the second table.
To avoid this error, insert into the [dbo].[tblsubject] table first before inserting to the [dbo].[tblSchedule] table.

Related

create a foreign key on a primary key of another table

CREATE TABLE public.impiegato(
CF varchar NOT NULL,
codice_reparto int4 NOT NULL,
mansione varchar NULL,
CONSTRAINT impiegato_pkey PRIMARY KEY (CF),
CONSTRAINT impiegato_fkey FOREIGN KEY (codice_reparto) REFERENCES reparto(codice),
);
CREATE TABLE public.reparto(
codice int4 NOT NULL,
nome varchar NULL,
cf_responsabile varchar NULL,
nome_responsabile varchar NULL UNIQUE,
CONSTRAINT reparto_pkey PRIMARY KEY (codice),
CONSTRAINT reparto_cf_responsabile_fkey FOREIGN KEY (cf_responsabile) REFERENCES impiegato(CF)
);
When i run the sql code it tells me that the impiegato table doesn't exist. Can I run a foreign key on a primary key of another table?
The referenced table must exists when a foreign key is declared.
Since in your case the two tables reference each other, it's not possible to solve this by simply creating the right one first.
You have to create the first one (any of them) first without the foreign key constraint, create the second on and then add the foreign key constraint to the first one.
Something along the lines of:
CREATE TABLE public.impiegato
(cf varchar
NOT NULL,
codice_reparto int4
NOT NULL,
mansione varchar
NULL,
CONSTRAINT impiegato_pkey
PRIMARY KEY (cf));
CREATE TABLE public.reparto
(codice int4
NOT NULL,
nome varchar
NULL,
cf_responsabile varchar
NULL,
nome_responsabile varchar
NULL
UNIQUE,
CONSTRAINT reparto_pkey
PRIMARY KEY (codice),
CONSTRAINT reparto_cf_responsabile_fkey
FOREIGN KEY (cf_responsabile)
REFERENCES impiegato
(cf));
ALTER TABLE public.impiegato
ADD CONSTRAINT impiegato_fkey
FOREIGN KEY (codice_reparto)
REFERENCES reparto
(codice);
Unfortunately, you didn't tag your DBMS. From some details I guessed it might be Postgres and the code above hence is Postgres code. If you don't use Postgres, you might need to adapt the ALTER TABLE statement, they can differ between DBMS.

SQL Script File is failing but not showing an error

I have ran this Script File on Oracle Application Express and it does not create my tables and does not state that I have errors. If you can't help that is okay, but I have been at this for hours and cannot figure out why it is not working
Here is my Script File:
CREATE TABLE GUEST_T
(GUEST_ID NUMBER NOT NULL,
GUEST_NAME VARCHAR(25),
GUEST_ADDRESS VARCHAR(30),
CONSTRAINT GUEST_PK PRIMARY KEY (GUEST_ID));
CREATE TABLE COMPANY_T
(GUEST_ID NUMBER NOT NULL,
GUEST_NAME VARCHAR(25),
COMPANY_NAME VARCHAR(25),
ADDRESS VARCHAR(30),
NO_OF_GUESTS INT,
CONSTRAINT COMPANY_PK PRIMARY KEY (GUEST_ID),
CONSTRAINT COMPANY_FK FOREIGN KEY (GUEST_ID) REFERENCES GUEST_T(GUEST_ID));
CREATE TABLE ACCOMMODATION_T
(ACCOMMODATION_ID NUMBER NOT NULL,
ACCOMMODATION_TYPE VARCHAR(25),
PRICE DECIMAL (6,2),
CONSTRAINT ACCOMMODATION_PK PRIMARY KEY (ACCOMMODATION_ID));
CREATE TABLE EMPLOYEE_T
(EMPLOYEE_ID NUMBER NOT NULL,
EMPLOYEE_NAME VARCHAR(25),
HOURS_WORKED INT,
CONSTRAINT EMPLOYEE_PK PRIMARY KEY (EMPLOYEE_ID));
CREATE TABLE RECEPTIONIST_T
(EMPLOYEE_ID NUMBER NOT NULL,
EMPLOYEE_NAME VARCHAR(25),
HOURS_WORKED INT,
HOURLY_WAGE DECIMAL (4,2),
CONSTRAINT RECEPTIONIST_PK PRIMARY KEY (EMPLOYEE_ID),
CONSTRAINT EMPLOYEE_FK FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID));
CREATE TABLE MANAGER_T
(EMPLOYEE_ID NUMBER NOT NULL,
EMPLOYEE_NAME VARCHAR(25),
HOURS_WORKED INT,
SALARY DECIMAL (10,2)
CONSTRAINT MANAGER_PK PRIMARY KEY (EMPLOYEE_ID),
CONSTRAINT EMPLOYEE_FK FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID));
CREATE TABLE ACCOMMODATION_REQUEST_T
(ACCOMMODATION_ID NUMBER NOT NULL,
GUEST_ID NUMBER NOT NULL,
EMPLOYEE_ID NUMBER NOT NULL,
TIME REQUESTED NUMBER,
DATE_OF_USE DATE DEFAULTSYSDATE,
CONSTRAINT ACCOMMODATION_REQUEST_PK PRIMARY KEY (ACCOMMODATION_ID, GUEST_ID, EMPLOYEE_ID),
CONSTRAINT ACCOMMODATION_REQUEST_FK1 FOREIGN KEY (ACCOMMODATION_ID) REFERENCES ACCOMMODATION_T(ACCOMMODATION_ID),
CONSTRAINT ACCOMMODATION_REQUEST_FK2 FOREIGN KEY (GUEST_ID) REFERENCES GUEST_T(GUEST_ID),
CONSTRAINT ACCOMMODATION_REQUEST_FK3 FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID));
CREATE TABLE ROOM_T
(ROOM_NO NUMBER NOT NULL,
FLOOR_NO NUMBER,
ROOM_PRICE DECIMAL (8,2),
ROOM_STATUS VARCHAR(20) CHECK (ROOM_STATUS IN (‘Vacant’, ‘Occupied’)),
CONSTRAINT ROOM_PK PRIMARY KEY (ROOM_NO),
CONSTRAINT ROOM_FK FOREIGN KEY (FLOOR_NO) REFERENCES FLOOR_T(FLOOR_NO));
CREATE TABLE DOUBLE_ROOM_T
(ROOM_NO NUMBER NOT NULL,
ROOM_PRICE DECIMAL (8,2),
ROOM_STATUS VARCHAR(20) CHECK (ROOM_STATUS IN (‘Vacant’, ‘Occupied’)),
ADJOINED VARCHAR(5) CHECK (ADJOINED IN (‘Yes’, ’No’)),
CONSTRAINT DOUBLE_ROOM_PK PRIMARY KEY (ROOM_NO),
CONSTRAINT DOUBLE_ROOM_FK1 FOREIGN KEY (ROOM_NO) REFERENCES ROOM_T (ROOM_NO),
CONSTRAINT DOUBLE_ROOM_FK2 FOREIGN KEY (FLOOR_NO) REFERENCES FLOOR_T (FLOOR_NO));
CREATE TABLE RESERVATION_T
(ROOM_NO NUMBER NOT NULL,
GUEST_ID NUMBER NOT NULL,
EMPLOYEE_ID NUMBER NOT NULL,
CHECK_IN_DATE DATE DEFAULTSYSDATE,
CHECK_OUT_DATE DATE DEFAULTSYSDATE,
NO_OF_ROOMS INT,
CONSTRAINT RESERVATION_PK PRIMARY KEY (ROOM_NO, GUEST_ID, EMPLOYEE_ID),
CONSTRAINT RESERVATION_FK1 FOREIGN KEY (ROOM_NO) REFERENCES ROOM_T(ROOM_NO),
CONSTRAINT RESERVATION_FK2 FOREIGN KEY (GUEST_ID) REFERENCES GUEST_T(GUEST_ID),
CONSTRAINT RESERVATION_FK3 FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID));
CREATE TABLE FLOOR_T
(FLOOR_NO NUMBER NOT NULL,
NO_OF_ROOMS INT,
CONSTRAINT FLOOR_PK PRIMARY KEY (FLOOR_NO));
CREATE TABLE FACILITY_T
(FACILITY_ID NUMBER NOT NULL,
FACILITY_NAME VARCHAR(25),
CONSTRAINT FACILITY_PK PRIMARY KEY (FACILITY_ID));
I have run this Script File on Oracle Application Express and it does not create my tables and does not state that I have errors. If you can't help that is okay, but I have been at this for hours and cannot figure out why it is not working.
There are a lot of issues in your script (and they do show up when the scripts runs). The most proeminent ones are:
the same constraint name is used in several tables; a constraint name must be unique in a schema, you can prefix them with the table name to avoid clashes
various typos : missing underscore, missing spaces, missing commas
funky quotes ‘’ instead of regular quotes
wrong table creation sequence: a parent table must be created before its dependant tables
side note: you want to use VARCHAR2, that Oracle recommends to replace VARCHAR
Here is a new version of your script that works fine in this DB fiddle. All the changes are commented:
CREATE TABLE GUEST_T (
GUEST_ID NUMBER NOT NULL,
GUEST_NAME VARCHAR2(25),
GUEST_ADDRESS VARCHAR2(30),
CONSTRAINT GUEST_PK PRIMARY KEY (GUEST_ID)
);
CREATE TABLE COMPANY_T (
GUEST_ID NUMBER NOT NULL,
GUEST_NAME VARCHAR2(25),
COMPANY_NAME VARCHAR2(25),
ADDRESS VARCHAR2(30),
NO_OF_GUESTS INT,
CONSTRAINT COMPANY_PK PRIMARY KEY (GUEST_ID),
CONSTRAINT COMPANY_FK FOREIGN KEY (GUEST_ID) REFERENCES GUEST_T(GUEST_ID)
);
CREATE TABLE ACCOMMODATION_T (
ACCOMMODATION_ID NUMBER NOT NULL,
ACCOMMODATION_TYPE VARCHAR2(25),
PRICE DECIMAL (6,2),
CONSTRAINT ACCOMMODATION_PK PRIMARY KEY (ACCOMMODATION_ID)
);
CREATE TABLE EMPLOYEE_T (
EMPLOYEE_ID NUMBER NOT NULL,
EMPLOYEE_NAME VARCHAR2(25),
HOURS_WORKED INT,
CONSTRAINT EMPLOYEE_PK PRIMARY KEY (EMPLOYEE_ID)
);
CREATE TABLE RECEPTIONIST_T (
EMPLOYEE_ID NUMBER NOT NULL,
EMPLOYEE_NAME VARCHAR2(25),
HOURS_WORKED INT,
HOURLY_WAGE DECIMAL (4,2),
CONSTRAINT RECEPTIONIST_PK PRIMARY KEY (EMPLOYEE_ID),
CONSTRAINT RECEPTIONIST_T_EMPLOYEE_FK -- constraint name must be unique
FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID)
);
CREATE TABLE MANAGER_T (
EMPLOYEE_ID NUMBER NOT NULL,
EMPLOYEE_NAME VARCHAR2(25),
HOURS_WORKED INT,
SALARY DECIMAL (10,2), -- missing comma here
CONSTRAINT MANAGER_PK PRIMARY KEY (EMPLOYEE_ID),
CONSTRAINT MANAGER_T_EMPLOYEE_FK -- constraint name must be unique
FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID)
);
CREATE TABLE ACCOMMODATION_REQUEST_T (
ACCOMMODATION_ID NUMBER NOT NULL,
GUEST_ID NUMBER NOT NULL,
EMPLOYEE_ID NUMBER NOT NULL,
TIME_REQUESTED NUMBER, -- missing underscore between TIME and REQUESTED
DATE_OF_USE DATE DEFAULT SYSDATE, -- missing space between DEFAULT and SYSDATE
CONSTRAINT ACCOMMODATION_REQUEST_PK PRIMARY KEY (ACCOMMODATION_ID, GUEST_ID, EMPLOYEE_ID),
CONSTRAINT ACCOMMODATION_REQUEST_FK1 FOREIGN KEY (ACCOMMODATION_ID) REFERENCES ACCOMMODATION_T(ACCOMMODATION_ID),
CONSTRAINT ACCOMMODATION_REQUEST_FK2 FOREIGN KEY (GUEST_ID) REFERENCES GUEST_T(GUEST_ID),
CONSTRAINT ACCOMMODATION_REQUEST_FK3 FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID)
);
-- must be created before the dependant tables (ROOM_T, DOUBLE_ROOM_T, ...)
CREATE TABLE FLOOR_T (
FLOOR_NO NUMBER NOT NULL,
NO_OF_ROOMS INT,
CONSTRAINT FLOOR_PK PRIMARY KEY (FLOOR_NO)
);
CREATE TABLE ROOM_T (
ROOM_NO NUMBER NOT NULL,
FLOOR_NO NUMBER,
ROOM_PRICE DECIMAL (8,2),
ROOM_STATUS VARCHAR2(20) CHECK (ROOM_STATUS IN ('Vacant', 'Occupied')), -- funky quotes ‘’
CONSTRAINT ROOM_PK PRIMARY KEY (ROOM_NO),
CONSTRAINT ROOM_FK FOREIGN KEY (FLOOR_NO) REFERENCES FLOOR_T(FLOOR_NO)
);
CREATE TABLE DOUBLE_ROOM_T (
ROOM_NO NUMBER NOT NULL,
ROOM_PRICE DECIMAL (8,2),
ROOM_STATUS VARCHAR2(20) CHECK (ROOM_STATUS IN ('Vacant', 'Occupied')), -- funky quotes ‘’
ADJOINED VARCHAR2(5) CHECK (ADJOINED IN ('Yes', 'No')), -- funky quote ‘’
CONSTRAINT DOUBLE_ROOM_PK PRIMARY KEY (ROOM_NO),
CONSTRAINT DOUBLE_ROOM_FK1 FOREIGN KEY (ROOM_NO) REFERENCES ROOM_T (ROOM_NO)
-- CONSTRAINT DOUBLE_ROOM_FK2 FOREIGN KEY (FLOOR_NO) REFERENCES FLOOR_T (FLOOR_NO) -- there is no such column
);
CREATE TABLE RESERVATION_T (
ROOM_NO NUMBER NOT NULL,
GUEST_ID NUMBER NOT NULL,
EMPLOYEE_ID NUMBER NOT NULL,
CHECK_IN_DATE DATE DEFAULT SYSDATE, -- missing space between DEFAULT and SYSDATE
CHECK_OUT_DATE DATE DEFAULT SYSDATE, -- missing space between DEFAULT and SYSDATE
NO_OF_ROOMS INT,
CONSTRAINT RESERVATION_PK PRIMARY KEY (ROOM_NO, GUEST_ID, EMPLOYEE_ID),
CONSTRAINT RESERVATION_FK1 FOREIGN KEY (ROOM_NO) REFERENCES ROOM_T(ROOM_NO),
CONSTRAINT RESERVATION_FK2 FOREIGN KEY (GUEST_ID) REFERENCES GUEST_T(GUEST_ID),
CONSTRAINT RESERVATION_FK3 FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE_T(EMPLOYEE_ID)
);
CREATE TABLE FACILITY_T (
FACILITY_ID NUMBER NOT NULL,
FACILITY_NAME VARCHAR2(25),
CONSTRAINT FACILITY_PK PRIMARY KEY (FACILITY_ID)
);

SQL Syntax error with foreign keys

now i have table place CREATE TABLE [dbo].[Place] (
[Place_Id] INT IDENTITY (1, 1) NOT NULL,
[Name] VARCHAR (50) NOT NULL,
[Building_Date] DATE NULL,
[Longitude] VARCHAR (50) NULL,
[Latitude] VARCHAR (50) NULL,
[Location] VARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([Place_Id] ASC)
); , and table Citeria CREATE TABLE [dbo].[Criteria] (
[Criteria] VARCHAR (50) NOT NULL,
[Place_Id] INT NOT NULL, PRIMARY KEY CLUSTERED ([Criteria], [Place_Id]), CONSTRAINT [FK_Criteria_ToTable] FOREIGN KEY (Place_Id) REFERENCES Place(Place_Id)
);and The referenced table '[dbo].[Criteria]' 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.
.
The error is correct. Subqueries are not allowed in check constraints.
But, you already have a foreign key reference between user_name and likes(user_name), so this condition is already in place. The only thing is would really be checking is that user_name is not NULL, but that is already true by the definition of the column.
Now, there are other issues. Your foreign keys should be to primary keys or unique keys in other tables. I think this is your intention:
CREATE TABLE [dbo].Normal_Upload
(
[User_Name] VARCHAR(50) NOT NULL ,
[Place_Id] INT NOT NULL,
[Image] IMAGE NOT NULL,
CONSTRAINT [FK_Normal_Upload] FOREIGN KEY (User_Name) REFERENCES Member(User_Name),
CONSTRAINT [FK_Normal_Upload_1] FOREIGN KEY (Place_Id) REFERENCES Place(Place_Id),
CONSTRAINT [FK_Normal_Upload_2] FOREIGN KEY (User_Name, Place_Id) REFERENCES Likes(User_Name, Place_Id)
);
As a note on naming. I think the primary keys of tables should include the table name. So, consider Member_Name rather than User_Name for the Member table.
It wrong db design, never use varchar or character type column in reference key or primary-key(try to avoid as much as possible).
For you solution, create a column "useid" with int datatype and give pk to it. and update the following table
CREATE TABLE [dbo].[Likes] (
[User_id] VARCHAR (50) Identity (1,1),
[User_Name] VARCHAR (50) NOT NULL,
[Place_Id] INT NOT NULL,
CONSTRAINT [PK_Likes] PRIMARY KEY CLUSTERED ([User_id] ASC, [Place_Id] ASC),
CONSTRAINT [FK_Likes_ToTable] FOREIGN KEY ([User_Name]) REFERENCES Normal ([User_Name]),
CONSTRAINT [FK_Likes_ToTable_1] FOREIGN KEY ([Place_Id]) REFERENCES [dbo].[Place] ([Place_Id]),
);

Error creating database with multiple primary key columns and referencing foreign key

I've been having an issue when creating a database. Each table has a primary key with many foreign keys used also. The issue I have is that I keep getting the error
SQL Error: ORA-02270: no matching unique or primary key for this column-list
02270. 00000 - "no matching unique or primary key for this column-list"
*Cause: A REFERENCES clause in a CREATE/ALTER TABLE statement
gives a column-list for which there is no matching unique or primary
key constraint in the referenced table.
*Action: Find the correct column names using the ALL_CONS_COLUMNS
catalog view
I don't know what is causing this and is flagging the PROJECT_RECORDS table as the issue. I have used the same method in the PROJECT_TABLES table.
SQL/Oracle
CREATE TABLE PROJECT_DB
(DB_ID number (3) NOT NULL primary key,
DB_NAME varchar2 (25) NOT NULL,
DB_DESCRIPTION varchar2 (75) NOT NULL,
DB_DATE date NOT NULL);
CREATE TABLE PROJECT_DATATYPE
(DATATYPE_NAME varchar2 (20) NOT NULL PRIMARY KEY,
DATATYPE_DATATYPE varchar2(50) NOT NULL);
CREATE TABLE PROJECT_TABLES (
PROJECT_ID number(3) not null references PROJECT_DB(DB_ID) on delete cascade,
PROJECT_FIELDNAME varchar2(25) not null,
PROJECT_DATATYPE varchar2(50) not null references PROJECT_DATATYPE(DATATYPE_NAME),
PROJECT_LENGTH number(3),
PROJECT_REQUIRED varchar2(8),
PROJECT_LISTCOLUMNID number (3) not null,
primary key(PROJECT_ID, PROJECT_LISTCOLUMNID));
CREATE TABLE PROJECT_RECORDS (
RECORDS_ROWID number(3) not null,
RECORDS_LISTCOLUMNID number (3) not null references PROJECT_TABLES(PROJECT_LISTCOLUMNID)on delete cascade,
RECORDS_LISTID number (3) not null,
RECORDS_RECORDVALUE varchar2 (25),
primary key(RECORDS_ROWID, RECORDS_LISTCOLUMNID));
commit;
The reasoning for adding multiple primary keys to the PROJECT_TABLES table is that the listcolumnid isn't unique.
If listcolumnid is not unique, you cannot put a foreign key constraint on it. A foreign key always refrences exatcly one parent row. So you probably should use both columns in your foreign key (assuming there is really a 1:n relation):
CREATE TABLE PROJECT_RECORDS (
RECORDS_ROWID number(3) not null,
RECORDS_ID number(3) not null,
RECORDS_LISTCOLUMNID number (3) not null,
RECORDS_LISTID number (3) not null,
RECORDS_RECORDVALUE varchar2 (25),
primary key(RECORDS_ROWID, RECORDS_LISTCOLUMNID),
foreign key fk_project_projectrecords (RECORDS_ID, RECORDS_LISTCOLUMNID) references PROJECT_TABLES(PROJECT_ID, PROJECT_LISTCOLUMNID)on delete cascade,
);
(The example is using your prefix naming convention, I would change RECORDS_ID to PROJECT_ID, same for RECORDS_LISTCOLUMNID)
The problem is with your syntax. You don't do this:
, fieldname datatype references (something)
You do this:
, primary key(somefield)
, foreign key (somefield) references sometable(somefield)

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