I have created two tables (emp and dept). Emp contains a foreign key (deptid). I am attempting to delete a row from the dept table and am receiving a foreign key constraint error. I then altered the emp table foreign key to add constraint and delete on cascade. The code is copied here
create table dept (
deptid int primary key,
deptname varchar(20),
locid int);
create table emp (
empid int primary key,
frname varchar(15),
lname varchar(20),
hiredate datetime,
deptid int,
foreign key (deptid) references dept(deptid));
alter table emp add constraint fk_deptid foreign key (deptid)
references dept(deptid) on delete cascade;
This is the error message that I receive:
Query Error: Error: ER_ROW_IS_REFERENCED_2: Cannot delete or update a parent row: a foreign key constraint fails (test.emp, CONSTRAINT emp_ibfk_1 FOREIGN KEY (deptid) REFERENCES dept (deptid))
The problem is that you are creating two foreign key constraints for the same column. Avoid doing this, it's confusing.
The first one is created while you create the table and is unnamed. Since you didn't provide a name for it, MySQL automatically names it for you as emp_ibfk_1. This one does not have CASCADE DELETE and prevents deletion of parent keys.
The second one is on a separate SQL statement and you name it fk_deptid. This one has CASCADE DELETE and allows deletion of parent keys.
While enforcing the foreign key constraints MySQL cannot delete the row since the first constraint does not allow it. That's the error you are getting.
This is a confusing situation and I would avoid doing something like this. I would suggest having a single FK constraint for the column; specifically I would remove the first one.
For example:
create table dept (
deptid int primary key,
deptname varchar(20),
locid int);
create table emp (
empid int primary key,
frname varchar(15),
lname varchar(20),
hiredate datetime,
deptid int
-- , foreign key (deptid) references dept(deptid) -- removed
);
alter table emp add constraint fk_deptid foreign key (deptid)
references dept(deptid) on delete cascade;
insert into dept (deptid, deptname, locid)
values (1, 'Math', 123);
insert into emp (empid, frname, lname, hiredate, deptid)
values (10, 'Peter', 'Fonda', null, 1);
delete from dept where deptid = 1; -- works!
Related
CREATE DATABASE employeeDB;
USE employeeDB;
CREATE TABLE employees(
employeeid NUMERIC(9),
firstname VARCHAR(10),
lastname VARCHAR(20),
deptCode CHAR(5),
salary NUMERIC(9, 2),
PRIMARY KEY (employeeid)
);
CREATE TABLE projects(
projectid CHAR(8),
deptcode CHAR(5),
description VARCHAR(200),
startdate DATE,
stopdate DATE,
revenue NUMERIC(12, 2),
PRIMARY KEY (projectid),
FOREIGN KEY (deptcode) REFERENCES employees(deptCode)
);
CREATE TABLE departments(
code CHAR(5),
name VARCHAR(5),
managerid NUMERIC(9),
subdeptof CHAR(5),
PRIMARY KEY (code),
FOREIGN KEY (managerid) REFERENCES employees(employeeid),
FOREIGN KEY (subdeptof) REFERENCES projects(deptcode)
);
ALTER TABLE employees ADD FOREIGN KEY (deptCode) REFERENCES projects(deptcode);
Something wrong at the line CREATE TABLE projects(...). When I run the code in MySQL it give the Error Code 1822. What is the problem ? Any expert can help ?
You cant create foreign key with a non-primary key, and if you really want to create foreign key to non-primary key (column), the column must be indexed with a unique constraint on it.
So either create unique constraint on deptCode column, or reference by already existing primary key, or change the primary key.
CREATE TABLE employee (
emp_id INT PRIMARY KEY,
first_name VARCHAR(40),
last_name VARCHAR(40),
birth_day DATE,
sex VARCHAR(1),
salary INT,
super_id INT,
branch_id INT
);
CREATE TABLE branch (
branch_id INT PRIMARY KEY,
branch_name VARCHAR(40),
mgr_id INT,
mgr_start_date DATE,
FOREIGN KEY(mgr_id) REFERENCES employee(emp_id) ON DELETE SET NULL
);
ALTER TABLE employee
ADD FOREIGN KEY(branch_id)
REFERENCES branch(branch_id)
ON DELETE SET NULL;
ALTER TABLE employee
ADD FOREIGN KEY(super_id)
REFERENCES employee(emp_id)
ON DELETE SET NULL;
ALTER TABLE employee DROP CONSTRAINT branch_id;
Trying to Drop Constraint branch_id error says 'Constraint 'branch_id' does not exist.'
All I want to do is drop the employee table.
First find the name of the constraint with
SHOW CREATE TABLE employee
The name isn't "branch_id".
The actual name of your foreign key constraint is not branch_id, it is something else. The better approach here would be to name the constraint explicitly:
ALTER TABLE employee
ADD CONSTRAINT fk_branch_id FOREIGN KEY (branch_id)
REFERENCES branch(branch_id);
Then, delete it using the explicit constraint name you used above:
ALTER TABLE employee DROP FOREIGN KEY fk_branch_id;
I try to create a table for the company database.
As I tried to add some foreign keys in there, something goes wrong.
CREATE TABLE employee (
emp_id INT PRIMARY KEY,
first_name VARCHAR(40),
last_name VARCHAR(40),
birth_day DATE,
sex VARCHAR(1),
salary INT,
super_id INT,
branch_id INT unique
);
CREATE TABLE branch (
branch_id INT PRIMARY KEY,
branch_name VARCHAR(40),
mgr_id INT,
mgr_start_date DATE,
FOREIGN KEY(mgr_id) REFERENCES employee(emp_id) ON DELETE SET NULL
);
ALTER TABLE employee
ADD FOREIGN KEY(branch_id)
REFERENCES branch(branch_id)
ON DELETE SET NULL;
ALTER TABLE employee
ADD FOREIGN KEY(super_id)
REFERENCES employee(emp_id)
ON DELETE SET NULL
The "alter table employee" part to add foreign key (branch) failed with the following statement.
ER_FK_NO_INDEX_PARENT: Failed to add the foreign key constraint. Missing index for constraint 'employee_ibfk_10' in the referenced table 'branch'
Could this be some problem with my setting?
I am not able to establish foreign key constrain in mysql.
Mysql version: 5.0
Queries I have used are:
create table department (
deptid varchar(10),
primary key (deptid),
name varchar(20)
);
create table employee (
empid varchar(10),
primary key (empid),
name varchar(20),
age int,
deptid varchar(10),
foreign key (deptid) references department (deptid)
);
I am still able to add employee with department id which is not present in department table.
Thanks.
EDIT: I changed engine for my tables but still this constraint is not working. I changed engine by using following query: alter table department engine=InnoDB;
As mmarinero suggested that foreign key constraint doesn't work for MyISAM engine. I checked engine for my tables using following query:
show table status;
It showed MyISAM engine for my tables.
I dropped my tables and recreated them using following queries:
create table department (deptid varchar(10), primary key (deptid), name varchar(20)) engine=InnoDB;
create table employee (empid varchar(10), primary key (empid), name varchar(20), age int, deptid varchar(10), foreign key (deptid) references department (deptid)) engine=InnoDB;
Now my foreign constraint is working.
Thanks mmarinero.
Trying to explain the REFERENCES CONSTRAINT to someone else with a MySQL example, and I can't make the pesky example work! It seems to work if I define it as a FOREIGN KEY, but I've textbooks that say I don't have to do that (making it a column-level referential constraint rather than a table-level one).
The question is, after the UPDATE to dname in the dept table, why doesn't the dname in the emp table change?
-- SQL CODE BEGINS
DROP TABLE IF EXISTS dept;
DROP TABLE IF EXISTS emp;
CREATE TABLE dept (
dname CHAR(10),
dnum numeric(3,0)
) ENGINE=InnoDB;
CREATE TABLE emp (
dname CHAR(10) REFERENCES dept(dname) ON UPDATE CASCADE,
ename CHAR(10)
) ENGINE=InnoDB;
INSERT INTO dept VALUES ("AAA", 111);
INSERT INTO dept VALUES ("BBB", 222);
INSERT INTO emp VALUES ("CCC", "Carol");
INSERT INTO emp VALUES ("AAA", "Alice");
SELECT * from dept;
SELECT * from emp;
UPDATE dept SET dname="XYZ" WHERE dnum=111;
SELECT * from dept;
SELECT * from emp;
-- SQL CODE ENDS
ARGH!
DECLARE dept.dname AS PRIMARY KEY
create a FOREIGN KEY constraint on emp.dname
FULL DDL:
CREATE TABLE dept
(
dname CHAR(10) PRIMARY KEY,
dnum numeric(3,0)
) ENGINE=InnoDB;
CREATE TABLE emp
(
dname CHAR(10) ,
ename CHAR(10),
CONSTRAINT em_FR FOREIGN KEY (dname)
REFERENCES dept(dname) ON UPDATE CASCADE
) ENGINE=InnoDB;
SQLFiddle Demo
excerpted from MySQL 5.5 Reference Manual
<snip>
InnoDB does not recognize or support “inline REFERENCES specifications” (as defined in the SQL standard) where the references are defined as part of the column specification. InnoDB accepts REFERENCES clauses only when specified as part of a separate FOREIGN KEY specification. For other storage engines, MySQL Server parses and ignores foreign key specifications.
</snip>
http://dev.mysql.com/doc/refman/5.5/en/create-table.html
I think the authors of your two textbooks should have noted that their recommended approach, adding "REFERENCES" clause on the column definition, does NOT create or enforce foreign key constraints.
In order to create a foreign key constraint, you need a unique index on the target column(s). In your case, you nee an index on dept(dname).
ALTER TABLE dept ADD CONSTRAINT dept_UX
UNIQUE KEY (dname) ;
With that in place, you can then create a foreign key constraint:
ALTER TABLE emp ADD CONSTRAINT FK_emp_dept
FOREIGN KEY (dname) REFERENCES dept(dname) ON UPDATE CASCADE ;
(Normally, a foreign key references the PRIMARY KEY of a table. But a UNIQUE KEY is sufficient. Actually, with InnoDB, all that is required is an index, it doesn't have to be unique, but we don't want to go there.)
To declare dname to be the PRIMARY KEY rather than a UNIQUE KEY:
ALTER TABLE dept ADD PRIMARY KEY (dname) ;
When the REFERENCES clause is added to the column definition, I believe that gets ignored by MySQL. (The syntax is accepted, but it doesn't get recorded in the data dictionary. If you're working with MyISAM it doesn't matter, since MyISAM doesn't enforce foreign key constraints.)
To create foreign key constraints as part of the table definition, I put that on a separate line:
CREATE TABLE emp (
dname CHAR(10),
ename CHAR(10),
CONSTRAINT FK_emp_dept FOREIGN KEY (dname) REFERENCES dept(dname)
) ENGINE=InnoDB ;