SQL Management Studio 2012 Foreign Key Is A Mess - sql

I am trying to add a foreign key to a table. I have created two tables.
CREATE TABLE madeupbusiness.staff
(
staffnum int NOT NULL,
forename varchar(30) NOT NULL,
surname varchar(30) NOT NULL,
meeting int NOT NULL,
PRIMARY KEY (staffnum),
)
GO
meeting should use the PK from from the meeting table to create a FK :
CREATE TABLE madeupbusiness.meeting
(
meetingnum int NOT NULL,
room varchar(30) NOT NULL,
PRIMARY KEY (meetingnum),
)
GO
To create the foreign key I run this query
ALTER TABLE madeupbusiness.staff
WITH CHECK
ADD CONSTRAINT FK_staff_meetingnum FOREIGN KEY (meetingnum)
REFERENCES madeupbusiness.meeting(meetingnum)
ON DELETE CASCADE
ON UPDATE CASCADE
;
GO
The query runs but when I create a database diagram there is a square loop the staff table from the staffnum key back onto it. Sorry but I don't really know how to describe it. There is no relationship between the two tables. What am I doing wrong?
I have tried to add the relationship from design view but the foreign key table is greyed out.

If you can rebuild the Table do this:
CREATE TABLE madeupbusiness.meeting
(meetingnum int NOT NULL PRIMARY KEY REFERENCES madeupbusiness.meeting(YourColumnYouWantItShouldBeReferenced),
room varchar(30) NOT NULL);
GO

Related

ERROR: violates foreign key constraint, key is not present in parent table (but it is??)

I know this question has been asked many times, but none of the answers have solved my issue.
I am creating a database for a uni assignment, using PostgreSQL through pgadmin 4, and I have a table named "staff" populated with staff members with a primary key of "staffid". I then have another table named "client_international", which includes a foreign key of "staffid" which relates to the staff tables primary key.
When trying to insert into the client table, I am getting the following error:
ERROR: insert or update on table "client_international" violates foreign key constraint "intclient_staff_fkey"
DETAIL: Key (staffid)=(100000024) is not present in table "staff".
SQL state: 23503
I am certain that that '100000024' key is in the staff table.. yet I still get the error. Any suggestions? Below I will paste the code I used to create the staff and client tables, in case anyone notices an error in them.
Staff table:
CREATE SEQUENCE staff_seq
start 100000000
increment 1;
CREATE TABLE staff
(
staffid integer default nextval('staff_seq'),
firstname varchar(20) NOT NULL,
lastname varchar(20) NOT NULL,
"position" varchar(20) NOT NULL,
mobile varchar(20) NOT NULL,
email varchar(100) NOT NULL,
"location" integer NOT NULL,
CONSTRAINT staff_pkey PRIMARY KEY (staffid)
);
Client table:
CREATE SEQUENCE client_seq
start 200000000
increment 1;
CREATE TABLE client
(
clientid integer default nextval('client_seq'),
company varchar(100) NOT NULL,
sector varchar(100) NOT NULL,
pointofcontact varchar(20) NOT NULL,
mobile varchar(20) NOT NULL,
email varchar(100) NOT NULL,
approvalstatus boolean default (false),
"location" integer NOT NULL,
staffid integer NOT NULL,
CONSTRAINT client_pkey PRIMARY KEY (clientid)
);
CREATE TABLE client_international
(
CONSTRAINT client_international_pkey PRIMARY KEY (clientid)
) INHERITS ("client");
ALTER TABLE client
ADD CONSTRAINT client_location_fkey FOREIGN KEY ("location") REFERENCES "location" (locationid),
ADD CONSTRAINT client_staff_fkey FOREIGN KEY (staffid) REFERENCES staff (staffid);
ALTER TABLE client_international
ADD CONSTRAINT intclient_location_fkey FOREIGN KEY ("location") REFERENCES "location" (locationid),
ADD CONSTRAINT intclient_staff_fkey FOREIGN KEY (staffid) REFERENCES staff (staffid);
I get the error when running the following statements:
INSERT INTO client_international(company, sector, pointofcontact, mobile, email, approvalstatus, "location", staffid)
VALUES ('Moores Dogs', 'Border Patrol', 'Carol Moore', '07911 653453', 'jenkinsj#k9solutions.co.uk', 'false', '500000001', '100000024');
Here's a screenshot of the entry in the staff table, showing that it's definitely in there:
Foreign keys aren't "inherited".
Quote from the manual
A serious limitation of the inheritance feature is that [...] foreign key constraints only apply to single tables, not to their inheritance children. This is true on both the referencing and referenced sides of a foreign key constraint.
(emphasis mine)
So what you are trying to do, simply isn't supported.

Missing Keyword in SQL Code on Foreign Keys unable to create the table

Trying to create a table with an SQL code, but I'm getting an error:
Missing keyword
in regards to the foreign key.
CREATE TABLE Staff
(
staffID VARCHAR(5) NOT NULL,
name VARCHAR(50),
position VARCHAR(30),
branchID VARCHAR(5),
PRIMARY KEY (staffID),
FOREIGN KEY (branchID) REFERENCES Branch ON UPDATE CASCADE
);
Unlike other RDBMS (such as MySQL for example), Oracle does not support the ON UPDATE clause in foreign keys. You would just need to remove that part of the declaration.
Try:
CREATE TABLE Staff (
staffID VARCHAR(5) NOT NULL,
name VARCHAR(50),
position VARCHAR(30),
branchID VARCHAR(5),
PRIMARY KEY (staffID),
FOREIGN KEY (branchID) REFERENCES Branch(branchID) --ON UPDATE CASCADE
);
Demo on DB Fiddle
The logic behind this Oracle behavior is that the referred column is not supposed to change, since it must be PRIMARY KEY (or a UNIQUE column). I believe that this limitation makes sense... they just don't want to give users enough rope to hang themselves with.

Are these FKs necessary -- and are they stopping me?

I'm having some difficulties with a database I'm creating for a summer camp, specifically with the PK and FK constraints. When I declare the FK constraint (e.g. FOREIGN KEY(PID) references Campers(CamperID)) I get an error running my code through pgAdmin (I'm using PostgreSQL). I understand that, for example, the Campers table is not yet created, and this is most likely part/all of the roadblock, however I feel like my FKs are still wrong somehow. To my understanding, a FK is a PK in another table -- but I feel like there is some redundancy or disconnect between my tables.
I've put the syntax for some of my CREATE statements below. I'm not sure if I'll get reprimanded for the quality of my (somewhat vague) question, but I feel a bit lost and would appreciate any help or advice. Thank you in advance!
DROP TABLE IF EXISTS People;
CREATE TABLE People (
PID VARCHAR(10) NOT NULL UNIQUE,
FName TEXT NOT NULL,
LName TEXT NOT NULL,
DOB DATE NOT NULL,
ArrivalDate DATE NOT NULL DEFAULT CURRENT_DATE,
DepartureDate DATE,
US_PhoneNum VARCHAR(11) NOT NULL,
StreetAddress VARCHAR(200) NOT NULL,
Sex GENDER NOT NULL,
ZIP VARCHAR(10) NOT NULL,
PRIMARY KEY(PID),
FOREIGN KEY(PID) REFERENCES Campers(CamperID),
FOREIGN KEY(PID) REFERENCES Counselors(CounselorID),
FOREIGN KEY(ZIP) REFERENCES Zip(ZIP)
);
DROP TABLE IF EXISTS Zip;
CREATE TABLE Zip (
ZIP VARCHAR(10) NOT NULL,
City TEXT NOT NULL,
State VARCHAR(2) NOT NULL,
PRIMARY KEY(ZIP)
);
DROP TABLE IF EXISTS Campers;
CREATE TABLE Campers (
CamperID VARCHAR(10) NOT NULL REFERENCES People(PID),
AgeGroup AGES NOT NULL,
CabinID VARCHAR(2) NOT NULL,
Bed BEDTYPES NOT NULL,
GroupID VARCHAR(3) NOT NULL,
PRIMARY KEY(CamperID),
FOREIGN KEY(CamperID) REFERENCES People(PID),
FOREIGN KEY(CabinID) REFERENCES Cabins(CabinID),
FOREIGN KEY(Bed) REFERENCES Beds(Bed),
FOREIGN KEY(GroupID) REFERENCES Groups(GroupID)
);
DROP TABLE IF EXISTS Counselors;
CREATE TABLE Counselors (
CounselorID VARCHAR(10) NOT NULL REFERENCES People(PID),
GroupID VARCHAR(3) NOT NULL,
CabinID VARCHAR(2) NOT NULL,
PRIMARY KEY(CounselorID),
FOREIGN KEY(GroupID) REFERENCES Groups(GroupID),
FOREIGN KEY(CabinID) REFERENCES Cabins(CabinID)
);
ERROR message for further clarification:
ERROR: relation "campers" does not exist
********** Error **********
ERROR: relation "campers" does not exist
SQL state: 42P01
There are more tables (obviously) which I can provide the create statements for, if needed.
You should really start here: Foreign key.
In the context of relational databases, a foreign key is a field (or
collection of fields) in one table that uniquely identifies a row of
another table.
What you are trying to do in your script is to create a circular link between People, Campers and Counselors. Having a Primary Key field also a Foreign Key mandates that IDs across all referenced tables are identical.
... and to create a Foreign Key the referenced table must already exist in the database. So you should start with the table that does not have any Foreign Keys and create tables that reference only those tables created previously. Alternatively you can create all tables without Foreign Keys and add them later, when all the tables are present.
... and to answer the question, Foreign Keys are never necessary, but they might help.

SQL Server perform a delete on all child records when deleting from a parent

I have 3 tables:
Create TABLE Subjects
(
SubjectID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
SubjectName VARCHAR(20) NOT NULL,
ClassID VARCHAR(10) FOREIGN KEY REFERENCES Classes(ClassID) NOT NULL
);
Create TABLE Topic
(
TopicID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
TopicName VARCHAR(100),
SubjectID INT FOREIGN KEY REFERENCES Subjects(SubjectID)
);
Create Table Worksheet
(
WorksheetName varchar(100) PRIMARY KEY,
TopicID INT Foreign KEY References Topic(TopicID),
Num_Q INT NOT NULL,
W_Type varchar(30)
);
Each one is a one to many relationship. When I try to delete from Subjects I get a foreign key constraint which is fine. What I want to know is how to get around this and perform a query to delete all relating aspects in a cascading style. I looked it up and there's but I am not sure how it works there seems to be multiple queries. Would it be better to create a trigger or is there a basic cascading function to do it all? I'm using visual studio to perform queries but not sure where the options to perform tasks like this are?
You can add the ON DELETE CASCADE right after the foreign key definition:
Create TABLE Subjects (
SubjectID INT PRIMARY KEY NOT NULL IDENTITY(1, 1),
SubjectName VARCHAR(20) NOT NULL,
ClassID VARCHAR(10) NOT NULL
FOREIGN KEY REFERENCES Classes(ClassID) ON DELETE CASCADE
);
You can also define it as a separate constraint, if you like, either within the CREATE TABLE statement or using ALTER TABLE ADD CONSTRAINT.
Here is the DDL for your Topic table with a CASCADE for delete. Its just a matter of defining it in your FK but using a slightly different syntax. This is for MS Sql Server.
CREATE TABLE Topic
(
TopicID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
TopicName VARCHAR(100),
SubjectID INT,
CONSTRAINT FK_Subjects_Topic FOREIGN KEY (SubjectID)
REFERENCES Subjects (SubjectID)
ON DELETE CASCADE
ON UPDATE NO ACTION
)
EDIT - added DELETE CASCADE on Worksheet table based on comment feedback.
Create Table Worksheet
(
WorksheetName varchar(100) PRIMARY KEY,
TopicID INT,
Num_Q INT NOT NULL,
W_Type varchar(30),
CONSTRAINT FK_Topic_Worksheet FOREIGN KEY (TopicID)
REFERENCES Topic (TopicID)
ON DELETE CASCADE
ON UPDATE NO ACTION
);
With this updated definition a delete on table Subjects will also delete child records in table Topics.

How to implement bidirectional referenced tables?

I have a table School and a table Teacher having a one-to-many relationship. However, one of the teachers is the school's principle, and only one teacher can be the school principle. So I thought of saving the teachers id (principle) in the School table as follows:
CREATE TABLE School (
ID INT PRIMARY KEY,
Name VARCHAR(40),
PrincipleID INT FOREIGN KEY REFERENCES Teacher.ID
)
CREATE TABLE Teacher (
ID INT PRIMARY KEY,
Name VARCHAR(40),
SchoolID INT FOREIGN KEY REFERENCES School.ID
)
I know I could loose the foreign key reference in the school table, but that's not an option.
Should I make the reference after the table creation? If yes, how?
Another solution is to create a new table, let's say SchoolsPrinciples with just two fields:
CREATE TABLE SchoolsPrinciples
(
SchoolId int,
TeacherId int,
CONSTRAINT uc_SchoolTeacher UNIQUE (SchoolId, TeacherId)
)
A UNIQUE constraint let you obtain exactly one teacher per each school.
When building the tables, you'll need to add the constraint as a separate alter statement. Note also that when creating foreign keys, you should only specify the table name, not the referenced column (the column is implied by the primary key).
CREATE TABLE School (
ID INT PRIMARY KEY,
Name VARCHAR(40),
PrincipleID INT);
CREATE TABLE Teacher (
ID INT PRIMARY KEY,
Name VARCHAR(40),
SchoolID INT
CONSTRAINT FK_Teacher_School
FOREIGN KEY REFERENCES School);
ALTER TABLE School add
CONSTRAINT FK_School_Teacher
FOREIGN KEY (PrincipleID) REFERENCES Teacher;
When you add data, you'll need to set the PrincipleID field as a separate update:
insert into School (ID, Name)
values (1, 'Blarg Elementary');
insert into Teacher (ID, Name, SchoolID)
values (1, 'John Doe', 1),
(2, 'Bob Smith', 1),
(3, 'Adam Walker', 1);
update School set PrincipleID = 2 where ID = 1;
Put a boolean IsPrincipal on the Teacher table instead. Or add a third relationship table
CREATE TABLE SchoolPrincipals (
INT SchoolID PRIMARY KEY FOREIGN KEY REFERENCES School.ID,
INT TeacherID FOREIGN KEY REFERENCES Teacher.ID
)
Keeps everything tidy without painful delete logic.
You can take a column in Teacher table as
IsPrincipal where only one row will have value as true as referred
by jonnyGold,
This can be checked by triggers.
OR
You can use filtered index if using Sql Server 2008.
Create unique filtered index where SchoolID, IsPrincipal
is NOT NULL and are unique
Boss where this will contain ID of principal hence creating employee manager relationship which in your case is not suitable.
CREATE TABLE EmpManager
(
TeacherID int
SchoolID int
IsPrincipal bit
)
And use filtered index or trigger to handle the scenario.
EDIT:
CREATE TABLE [dbo].[Teacher](
[ID] [int] NOT NULL primary key,
[Name] [varchar](40) NULL,
[SchoolID] [int] NULL,
)
GO
CREATE TABLE [dbo].[School](
[ID] [int] NOT NULL primary key,
[Name] [varchar](40) NULL,
[PrincipleID] [int] NULL,
)
GO
ALTER TABLE [dbo].[Teacher] WITH CHECK ADD CONSTRAINT [FK_Teacher_School] FOREIGN KEY([SchoolID])
REFERENCES [dbo].[School] ([ID])
GO
ALTER TABLE [dbo].[School] WITH CHECK ADD CONSTRAINT [FK_School_Teacher] FOREIGN KEY([PrincipleID])
REFERENCES [dbo].[Teacher] ([ID])
GO
Better design should be the one suggested by ADC