MySQL: Cannot add foreign key constraint Error - mysql

The first table is LocationTime table and the second table is Student table.
I am adding a Foreign Key using 'ALTER'. But I got the error below. Why am I getting the error?
Cannot add foreign key constraint Error
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| CourseN | varchar(3) | NO | PRI | NULL | |
| Quarter | varchar(11) | NO | PRI | NULL | |
| DayTime | varchar(7) | NO | PRI | NULL | |
| RoomN | varchar(3) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| studentName | varchar(15) | NO | PRI | NULL | |
| CourseN | varchar(3) | NO | PRI | NULL | |
| Quarter | varchar(11) | NO | PRI | NULL | |
+-------------+-------------+------+-----+---------+-------+
ALTER TABLE Student
ADD FOREIGN KEY (Quarter) REFERENCES LocationTime (Quarter)
ON UPDATE CASCADE ON DELETE SET NULL;

The problem is the fact that Quarter is a member of a composite key (CouresN, Quarter and DayTime forms the primary key for the LocationTime table). It is not possible to declare a Foreign Key Constraint on another table that is associated only with the Quarter, it should also include the other parts of the composite key. One possible solution to your problem it would be to declare other columns as your primary keys. Furthermore, I don't see the reason why you don't use a column with a auto generated INT (IDENTITY) as you primary key, or a column with an auto generated GUID.

If you are trying to INSERT a value into the table table_1 that does not exist in the table table_2 then you will get the error.
Since you have a Foreign Key on the table_1 field, you have to have the same value in the table_2.
See a non-working demo. This demo shows that the value for Codigo does not exist in the Fabricantes table so it throws the error message. Here is a working demo which shows that the value is in the table first.

Related

Properly creating a relational database

I have a database with three tables.
The table Authentication contains the following:
+----------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-----------------+------+-----+---------+----------------+
| id | int(6) unsigned | NO | PRI | NULL | auto_increment |
| userid | varchar(30) | NO | | NULL | |
| password | varchar(30) | NO | | NULL | |
| role | varchar(20) | NO | | NULL | |
| email | varchar(50) | YES | | NULL | |
+----------+-----------------+------+-----+---------+----------------+
Login contains the following:
+--------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------+------+-----+---------+----------------+
| id | int(6) unsigned | NO | PRI | NULL | auto_increment |
| TimeLoggedIn | text | NO | | NULL | |
| sessionid | varchar(255) | NO | | NULL | |
+--------------+-----------------+------+-----+---------+----------------+
And Activity:
+----------+-----------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-----------------+------+-----+---------+-------+
| id | int(6) unsigned | NO | PRI | NULL | |
| Torrents | mediumtext | NO | | NULL | |
+----------+-----------------+------+-----+---------+-------+
There is a relation between the id fields of Authentication to id in the other tables.
I need to add multiple rows in Activity, with several values for Torrents for each id. Unfortunately, when I try adding a new row with duplicated id value with:
INSERT INTO `Activity` (`id`, `Torrents`) VALUES ('1', 'dssfsdffdsffs');
it gives me the error: #1062 - Duplicate entry '1' for key 'PRIMARY'
How do I solve it? How did I create the table wrong?
I've read the following apparently duplicate questions:
#1062 - Duplicate entry for key 'PRIMARY'
But though it says to remove it as my primary key, mysql didnt allow me to create a relationship unless I made it a primary key.
You cannot initiate one-to-many relation by referring primary key to primary key. That'll be a one-to-one relationship.
In both your Login and Activity tables you need to have a foreign key to refer back to Authentication's ID. Example:
CONSTRAINT `FK_Login` FOREIGN KEY (`AuthenticationID`) REFERENCES `Authentication` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE

MySQL foreign key constraints through more tables

I find myself stack to this problem. I've got the following 3 tables, which I can't modify (it'd be so nice):
Person
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| SSN | varchar(50) | NO | PRI | NULL | |
| name | varchar(50) | YES | UNI | NULL | |
| birthday | date | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
Employee
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| SSN | varchar(50) | NO | PRI | NULL | |
| department | varchar(50) | YES | | NULL | |
| salary | varchar(50) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
Employer
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| name | varchar(50) | NO | PRI | NULL | |
| department | varchar(50) | YES | | NULL | |
| salary | varchar(50) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
Contract
+----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| employer_name | varchar(50) | NO | PRI | NULL | |
| employee_name | varchar(50) | YES | PRI | NULL | |
+----------------+-------------+------+-----+---------+-------+
I know that:
employee(sin) is foreign key to person(sin),
employer(name) is foreign key to person(name),
contract(employer_name) is a foreign key to employer(name)
And I should insert another foreign key for contract(employee_name), though employee table has only the SSN. Is there a way to reference the foreign key to person.name, passing through employee table, something like
CONSTRAINTS FOREIGN KEY contract(employee_name) REFERENCES TO person(name) WHERE person(sin)=employee(sin);
?
Thank you very much for any help!
An SQL FK constraint says its referencing column list subrow values, if all non-NULL, have to appear as subrow values for its referenced column list, which must be declared UNIQUE/PK in a base table.
Your constraint is not an SQL FK constraint.
If we could use a query in the place of the referenced base table name in an SQL FK constraint then the constraint you would want would be:
Contract(person_name) REFERENCES
(SELECT name FROM Person p JOIN Employee e ON p.name = e.name)(name)
(It can be shown that name is UNIQUE in that table.) But we can't.
If MySQL supported CREATE ASSERTION then you could CHECK that every Contract person_name was IN (SELECT name FROM Person p JOIN Employee e ON p.name = e.name). But it doesn't.
So this is an example of a constraint that, if you can't redesign your tables, you would enforce by appropriate triggers when the tables involved change.
Is there a way to reference the foreign key to person.name, passing through employee table, something like
If you want to figure out situations like this then you have to forego the cop-outs of using precise terms like "foreign key" just because you are somehow reminded of the things they refer to but that aren't there, or using the poetic "passing through", or using the vague "something like". You have to actually write out the conditions that you want your tables to satisfy.

"key column doesn't exist in table"

I'm making a database in MySQL in class and I'm having trouble adding foreign keys to my tables. I already added most of the foreign keys to my tables when I created the tables but obviously I couldn't add all of them in the creation process. I'm trying to add the remaining foreign keys with the below method.
ALTER TABLE ORDERS
ADD FOREIGN KEY (customer_sid) REFERENCES CUSTOMER(SID);
For some reason the error message listed in the title keeps popping up. The code is below. I can see the tables are coming out a bit funny but if you read them from left to right you can see what it says. What do you think?
mysql> show columns from games;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| gameID | int(11) | NO | PRI | NULL | auto_increment |
| videoGames | varchar(30) | NO | | NULL | |
| year | int(11) | NO | | NULL | |
| genreID | int(11) | NO | MUL | NULL | |
| companyID | int(11) | NO | MUL | NULL | |
| directorID | int(11) | NO | MUL | NULL | |
+------------+-------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
mysql> show columns from consoles;
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| consoleID | int(11) | NO | PRI | NULL | auto_increment |
| console | varchar(20) | NO | | NULL | |
| yearReleased | int(11) | NO | | NULL | |
+--------------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> alter table games
-> add foreign key(consoleID) references consoles(consoleID);
ERROR 1072 (42000): Key column 'consoleID' doesn't exist in table
There is no field consoleID in your table games. You need to create it before trying to add a constraint on it. This will add consoleID and create the constraint:
ALTER TABLE games ADD COLUMN consoleID INTEGER NOT NULL;
ALTER TABLE games ADD FOREIGN KEY (consoleID) REFERENCES consoles(consoleID);
You should think about adding a third table where you associate consoles with games because some games are multiplateform. :)

Are multiple foreign keys allowed?

I have multiple tables and I want multiple foreign keys.
Users Table
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| idUsers | int(11) | NO | PRI | NULL | |
| Username | varchar(45) | YES | | NULL | |
| Password | varchar(45) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
Friends Table
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| idUser | int(11) | YES | MUL | NULL | |
| idFriend | int(11) | YES | MUL | NULL | |
| Status | varchar(45) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
Groups Table
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| idGroup | int(11) | NO | PRI | NULL | |
| GroupName | varchar(45) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
Members Table
+----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| idGroup | int(11) | YES | MUL | NULL | |
| idMember | int(11) | YES | MUL | NULL | |
+----------+---------+------+-----+---------+-------+
This is the foreign key for my Members Table so that the idGroup and idMember both correspond to the Users table idUsers.
ALTER TABLE `GroupOrder`.`Friends`
ADD CONSTRAINT `idFriend`
FOREIGN KEY (`idFriend`)
REFERENCES `GroupOrder`.`Users` (`idUsers`)
ON DELETE CASCADE
ON UPDATE CASCADE;
I want to make another foreign key in the Friends table that corresponds to the Users table. Am I'm doing in wrong. Everytime I do this I get an error.
ALTER TABLE `GroupOrder`.`Friends`
ADD CONSTRAINT `idFriend`
FOREIGN KEY (`idUser` , `idFriend`)
REFERENCES `GroupOrder`.`Users` (`idUsers` , `idUsers`)
ON DELETE CASCADE
ON UPDATE CASCADE;
Error
ERROR 1005: Can't create table 'GroupOrder.#sql-2fce_1e' (errno: 150)
SQL Statement:
ALTER TABLE `GroupOrder`.`Friends`
ADD CONSTRAINT `idFriend`
FOREIGN KEY (`idUser` , `idFriend`)
REFERENCES `GroupOrder`.`Users` (`idUsers` , `idUsers`)
ON DELETE CASCADE
ON UPDATE CASCADE
ERROR: Error when running failback script. Details follow.
ERROR 1050: Table 'Friends' already exists
SQL Statement:
CREATE TABLE `Friends` (
`idUser` int(11) DEFAULT NULL,
`idFriend` int(11) DEFAULT NULL,
`Status` varchar(45) DEFAULT NULL,
KEY `idUser_idx` (`idFriend`),
KEY `idUser_idx1` (`idUser`,`idFriend`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
I am assuming friends is a many to many mapping from users to users. This sort of implies friendship can be one-way, but that isn't necessarily wrong.
You already mapped idfriend in friends to idusers in users, now map iduser in friends to idusers in users.
ALTER TABLE `GroupOrder`.`Friends`
ADD CONSTRAINT `idFriend2`
FOREIGN KEY (`idUser`)
REFERENCES `GroupOrder`.`Users` (`idUsers`)
ON DELETE CASCADE
ON UPDATE CASCADE;
Now, you probably want to enforce uniqueness of iduser and idfriend in friends so you don't have repetition.
alter table `grouporder`.friends`
add unique(oduser, idfriend);

MySQL foreign key constraint not applying?

I have the tables Players and PlayerMeta
mysql> DESCRIBE Players;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| ID | int(5) | NO | PRI | NULL | auto_increment |
| PlayerName | varchar(20) | NO | PRI | NULL | |
| Birthdate | date | YES | | NULL | |
| Location | varchar(20) | YES | | NULL | |
| FirstName | varchar(15) | YES | | NULL | |
| Whitelisted | tinyint(1) | NO | | 1 | |
+-------------+-------------+------+-----+---------+----------------+
mysql> DESCRIBE PlayerMeta;
+----------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------+------+-----+---------+-------+
| ID | int(5) | NO | PRI | NULL | |
| JoinDate | date | YES | | NULL | |
| BuildQuota | int(2) | NO | | 2 | |
| RegisteredDate | date | YES | | NULL | |
| HideBirthdate | tinyint(1) | NO | | 0 | |
+----------------+------------+------+-----+---------+-------+
I am trying to execute this command, and it returns Query OK:
ALTER TABLE PlayerMeta
ADD CONSTRAINT fk_PlayerID
FOREIGN KEY (ID)
REFERENCES Players(ID)
ON UPDATE CASCADE
ON DELETE CASCADE;
Yet, when I run SHOW CREATE TABLE PlayerMeta, it does not show the constraint, nor is it in INFORMATION_SCHEMA
Any thoughts? Thanks.
EDIT: Here is SHOW CREATE TABLE PlayerMeta:
mysql> SHOW CREATE TABLE PlayerMeta;
... a bunch of lines ...
| PlayerMeta | CREATE TABLE `PlayerMeta` (
`ID` int(5) NOT NULL,
`JoinDate` date DEFAULT NULL,
`BuildQuota` int(2) NOT NULL DEFAULT '2',
`RegisteredDate` date DEFAULT NULL,
`HideBirthdate` tinyint(1) NOT NULL DEFAULT '0',
UNIQUE KEY `ID` (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
EDIT(2): The problem was ID in PlayerMeta was already a primary key and a foreign key would not apply in conjunction with it.
You cannot create foreign keys for MyISAM.
Only InnoDB supports them.
So the solution for you is to change the storage engine for both tables.
ALTER TABLE Players ENGINE=InnoDB;
ALTER TABLE PlayerMeta ENGINE=InnoDB;
Then re-apply your ALTER with adding a FK constraint.
MySQL will not permit you to create a FOREIGN KEY constraint on a column which is itself a PRIMARY KEY. If your design is such that the two tables share a one-to-one relationship and both hold information about a Player, it may not make sense to separate them and instead combine both tables into one.
In any case, if you wish to keep them separate and enforce a FOREIGN KEY relationship on them, you need to remove the PRIMARY KEY on PlayerMeta.ID. You may still have a UNIQUE, non primary key index on it.