Cannot add foreign key constraint SQL when building schema - mysql

I'm taking a intro to database class right now. For a homework assignment I was given a piece of SQL code and told to just run some queries and give the results back. The problem is I can't even build the schema given with the code my teacher gave me. Here is this code:
CREATE TABLE emp (
name char(15),
dno int,
FOREIGN KEY (dno) REFERENCES dept(dno)
ON DELETE SET NULL
ON UPDATE CASCADE
);
CREATE TABLE dept (
dno int,
location char(30)
);
INSERT INTO emp(name,dno) VALUES
("Tom",111),
("Mary",111),
("Jack",222),
("Henry",222);
INSERT INTO dept(dno, location) VALUES
(111,"Irvine"),
(222,"LA"),
(333,"SF");
When this runs I get a error saying Cannot add foreign key constraint. I tried doing this via MySQL workbench and SQL Fiddle, both of which produce the same error. I don't really know whats wrong with the code given to me though and after looking online, couldn't seem to see anything obvious.

It may be part of the exercise for you to figure this out. However, assuming that it is not, here are important observations:
The foreign key reference should be to a primary key, and neither table has primary keys.
The table being referenced has to be defined before it can be referred to.
You can work on fixing these problems. Here is a SQL Fiddle with the right definitions.

The definition of the first table (emp) has a reference to a table that has not yeat been created (dept).You have to create first 'dept' to create a foreign key of it into another table.
Execute the queries in this order:
CREATE TABLE dept (
dno int,
location char(30)
);
CREATE TABLE emp (
name char(15),
dno int,
FOREIGN KEY (dno) REFERENCES dept(dno)
ON DELETE SET NULL
ON UPDATE CASCADE
);
INSERT INTO emp(name,dno) VALUES
("Tom",111),
("Mary",111),
("Jack",222),
("Henry",222);
INSERT INTO dept(dno, location) VALUES
(111,"Irvine"),
(222,"LA"),
(333,"SF");

try :CONSTRAINT dno_fk FOREIGN KEY (dno) REFERENCES dept(dno)
ON DELETE CASCADE

Related

Struggling to figure out a syntax error for a MySQL create table statement in regards to a foreign key reference

I've been wracking my brain for quite a while trying to figure out what is wrong with the first foreign key reference in the Property create table statement below. To isolate the error, I attempted to delete the foreign key reference and just create the table with the second foreign key reference in the Property table (ie: vendorId -> Vendor(vendorId)) and the table was able to be created with no issues. Thus, I believe I may have a design flaw on my hands which has me concerned. Both of the referenced tables have been created as well so that is not the issue. Help would be greatly appreciated, thanks! (Apologies if its some kind of dumb syntax error I'm not seeing)
Error is at line 11 in the Property create table statement:
error #1064 You have an error in your SQL syntax
Line 11: PRIMARY KEY (pid, vendorId),
Line 12: FOREIGN KEY (apptStatus) REFERENCES AgentSchedule(apptStatus)
Here is the code for the Property table referencing the AgentSchedule table as well as the Vendor table
CREATE TABLE Property(
pid INTEGER,
vendorId INTEGER,
houseDescr CHAR(150),
photoCopy CHAR(5),
propertyAddr CHAR(50),
apptStatus CHAR(5) DEFAULT 'False',
numVisits INTEGER,
propertyComments CHAR(150),
isEmpty CHAR(5),
PRIMARY KEY (pid, vendorId),
FOREIGN KEY (apptStatus) REFERENCES AgentSchedule(apptStatus)
ON DELETE SET DEFAULT
ON UPDATE CASCADE,
FOREIGN KEY (vendorId) REFERENCES Vendor(vendorId)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT TOF CHECK(photoCopy IN ('True','False')
AND apptStatus IN ('True', 'False')
AND isEmpty IN ('True', 'False'))
)
Here is the code for the referenced table corresponding to the first foreign key reference in the Property table.
CREATE TABLE AgentSchedule(
aid INTEGER,
propertyId INTEGER,
apptTime DATE UNIQUE,
apptStatus CHAR(5),
sickOrHolidays CHAR(5),
PRIMARY KEY (aid, propertyId),
CONSTRAINT TOF CHECK( apptStatus IN ('True', 'False')
AND sickOrHolidays IN ('True', 'False'))
)
Here is the referenced table corresponding to the second foreign key reference in the Property table.
CREATE TABLE Vendor(
vendorId INTEGER,
name CHAR(50),
phone INTEGER,
faxNum INTEGER,
PRIMARY KEY (vendorId),
CONSTRAINT PHONE CHECK(Phone >= 1000000000 AND Phone <= 9999999999
AND faxNum>= 1000000000
AND faxNum <= 9999999999)
)
Your problem is with the ON DELETE SET DEFAULT clause. Although MySQL recognises that clause, it is not allowed in table definitions. From the manual:
SET DEFAULT: This action is recognized by the MySQL parser, but both InnoDB and NDB reject table definitions containing ON DELETE SET DEFAULT or ON UPDATE SET DEFAULT clauses.
If you remove the SET DEFAULT clause the table creation works fine. Demo. If you need this functionality you can probably implement it via a ON DELETE trigger.

MySQL Error Code: 1824. Failed to open the referenced table

When I try to create the 'Project table I get this error Code: 1824. Failed to open the referenced table 'Employee'.
My syntax:
CREATE DATABASE IF NOT EXISTS Test;
USE Test;
CREATE TABLE IF NOT EXISTS Customer (
CustomerID VARCHAR(7) NOT NULL,
CustomerName VARCHAR(50),
CustAdress VARCHAR(70),
CustEmail VARCHAR(50),
PRIMARY KEY (CustomerID)
);
CREATE TABLE IF NOT EXISTS Employee (
EmpID VARCHAR(7) NOT NULL,
EmpName VARCHAR(50),
Position VARCHAR(30),
EmpTimePrice INT(4),
PRIMARY KEY (EmpID)
);
CREATE TABLE IF NOT EXISTS Project (
ProjectNo VARCHAR(7),
ProjectName VARCHAR(50),
StartDate DATE,
ProjTimePrice INT(6),
CustomerID VARCHAR(7),
EmpID VARCHAR(7),
PRIMARY KEY (ProjectNo),
FOREIGN KEY (EmpID) REFERENCES Employee (EmpID),
FOREIGN KEY (CustomerID) REFERENCES Customer (CustomerID)
);
CREATE TABLE IF NOT EXISTS ProjectWork (
ProjectNo VARCHAR(7),
EmpID VARCHAR(7),
PWDATE DATE,
HoursWorked INT(5),
FOREIGN KEY (ProjectNo) REFERENCES Project (ProjectNo),
FOREIGN KEY (EmpID) REFERENCES Employee (EmpID)
);
The names look correct to me and I have referenced the foreign key so I don't understand why I get this error. Any help would be appreciated, thanks.
This normally happens when the two tables have different Table engines. so check both tables if they have same table engines. for example MYISAM do not support Foreign Keys
Just edited EmpID to empID and it worked for some reason.
One of the easiest ways to get this error is referencing a table that doesn't exist yet. Eg if you run the following code on a new schema:
create table ttest (bob varchar(10) not null,
constraint fkbob foreign key (bob) references other(bob) );
... you will get the MySQL error:
Error Code: 1824. Failed to open the referenced table 'other'
Because the other table doesn't exist.
The code in the question above creates Employee before referencing it. However, note that the CREATE DATABASE and CREATE TABLE statements have IF EXISTS, but there are no DROP IF EXISTS statements, as when creating a new database. If you were debugging a table creation script, changing and fixing things as you go, it would have been pretty easy to get into an inconsistent state where the tables were out of synch with the code. This would also explain why other people could run the code cleanly, because these tables didn't exist in their schema yet.

What have I done wrong here

I am relatively new to the database world so bear with me. I'm just trying to add foreign key constraints and I keep getting error 1215 "cannot add foreign key constraint".
CREATE TABLE InProcessSamples
(
SampleNumber Int(6),
WorkOrder Int(8),
DueDate Date,
BeginsTesting Date,
FinishedTesting Date,
CONSTRAINT fk_sample_number FOREIGN KEY(SampleNumber) REFERENCES AllRecords(SampleNumber),
CONSTRAINT fk_work_order FOREIGN KEY(WorkOrder) REFERENCES SamplesReceived(WorkOrder)
);
CREATE TABLE SamplesReceived
(
WorkOrder Int(8) PRIMARY KEY,
SampleNumber Int(6),
RecTimeStamp DateTime,
PartNumber Int(10),
Description Char(36),
CONSTRAINT fk_sample_number FOREIGN KEY(SampleNumber) REFERENCES AllRecords(SampleNumber),
CONSTRAINT fk_part_number FOREIGN KEY(PartNumber) REFERENCES PartNumbers(PartNumber)
);
CREATE TABLE AllRecords
(
SampleNumber Int(6) PRIMARY KEY,
WorkOrder Int(8),
DueDate Date,
BeginsTesting Date,
FinishedTesting Date,
RecTimeStamp DateTime,
MeasurementOne Double,
MeasurementTwo Double,
PassDielectric Char(3),
PassedAllTest Char(3),
CONSTRAINT fk_work_order FOREIGN KEY(WorkOrder) REFERENCES SamplesReceived(WorkOrder),
CONSTRAINT fk_part_number FOREIGN KEY(PartNumber) REFERENCES PartNumbers(PartNumber)
);
CREATE TABLE PartNumbers
(
PartNumber Int(10) PRIMARY KEY,
Description Char(36)
);
Regardless of whether your design is off or not, you can't declare a foreign key reference to a table you haven't created yet.
CREATE TABLE statements are evaluated in order from top to bottom of your SQL script. As MySQL is trying to create the first table, the second and third tables don't exist yet. So there's nothing for the foreign keys to reference.
You should create tables in an order that allows the referenced table to exist before you create the table that has the foreign key to reference it. In this case, you have a circular dependency, so the only way to do it is to create either SamplesReceived or AllRecords without one of its foreign keys, and then go back afterward and add that foreign key.
CREATE TABLE PartNumbers, because it's needed by SamplesReceived and AllRecords
CREATE TABLE SamplesReceived, because it's needed by InProcessSamples and AllRecords
CREATE TABLE AllRecords, because it's needed by InProcessSamples
ALTER TABLE SamplesReceived ADD FOREIGN KEY(SampleNumber) REFERENCES AllRecords(SampleNumber);
CREATE TABLE InProcessSamples
That's if the circular reference is really needed.
But as other folks have answered, perhaps your circular reference isn't really a good design.
The circular reference could be needed; what it does in your case is enforce that for every row in SamplesReceived, you must have a matching row in AllRecords, and vice-versa, every row in AllRecords must have a matching row in SamplesReceived.
I don't know why that's important in your application. It might be, but you haven't told us anything about the workflow you're trying to model so I can't tell.
the normalization is all wrong:
this one is good:
Part
---------------
Part_id
Description
then you have redundancies and other issues everywhere...
maybe start with this:
WorkOrder
-------------
workorder_id
Sample
----------
sample_id
workorder_id
part_id
Test
--------------
test_id
description
min_passing_value
max_passing_value
TestResult
---------------
testresult_id
test_id
description
result_value
test_date
sample_id

How to make foreign key update based on parent

I have two tables, and I've made a relation using the Designer between the id column of my first table to the user_id column of my second table. Where and how do I add code or do something so that when, for example, the parent (id) is deleted, the user_id values which correspond to the deleted id will also be deleted? I tried deleting one of the registered ids, but the corresponding rows in the child table didn't get deleted.
I've done some searching, but I'm still very confused.
Thank you.
Note: I'm experimenting with MySQL and PHP, and this is for a little blog I'm making.
Please add an ON DELETE referential action to the foreign key constraint.
More details could be found here:
https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
For your case, ON DELETE CASCADE should be fine.
set id from first table as primary key
CREATE TABLE tbl_first(id INT PRIMARY KEY AUTO_INCREMENT, name varchar(20))
create your second table as tbl_second
CREATE TABLE tbl_second(id INT PRIMARY KEY AUTO_INCREMENT, fk_id int)
add constraint like this:
alter table tbl_second
add constraint fk_first
foreign key tbl_second(fk_id)
references tbl_first(id)
on delete cascade
it seem SQL Server and mySql are a little different, but it should work, i test it in mySQL

MySQL Foreign Key Referencing WHERE field=value

I have a table created in MySQL (see the code below). As you see in the code I have a foreign key manager which references the idNo. However I only want to reference to employees with the cat='B'. So I need something like
FOREIGN KEY (manager ) REFERENCES Employee(idNo WHERE cat='B').
Any ideas how I can accomplish this.
idNo SMALLINT AUTO_INCREMENT UNIQUE,
name VARCHAR(25) NOT NULL,
telNo INT(11) NOT NULL,
cat CHAR(1) NOT NULL,
manager SMALLINT,
PRIMARY KEY (idNo ),
FOREIGN KEY (manager ) REFERENCES Employee(idNo) on DELETE CASCADE)ENGINE=INNODB
AUTO_INCREMENT=1000;
Foreign keys do not allow conditions.
If you want to force the condition, you must do it via coding.
It can be done inside your non DB code (Java, PHP, VB,...), or you could create a procedure in MySQL that would be called to perform the insert and that will return an error code if condition is not matched.
If you insert from various codes/application, the procedure is the way to go since it would be centralized.
Create a new UNIQUE KEY in Employee combining idNo and cat.
ALTER TABLE Employee ADD UNIQUE KEY (idNo,cat);
Make a foreign key in the child table that references that new unique key.
ALTER TABLE SomeTable ADD FOREIGN KEY (idNo,cat) REFERENCES Employee(idNo,cat);
Then you just need to make sure cat is constrained to the single value 'B' in the child table. One solution is to create a lookup table containing just the single value 'B'.
CREATE TABLE JustB (cat char(1) PRIMARY KEY);
ALTER TABLE SomeTable ADD FOREIGN KEY(cat) REFERENCES JustB(cat);
Now the only value you can use in the child table is 'B', so naturally it can only reference rows in Employee that have a cat of 'B'.
Another solution would be to use a trigger, but I favor the lookup table.