MySQL foreign key constraint not applying? - mysql

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.

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: Cannot add foreign key constraint Error

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.

MySQL Workbench; creating intermediate tables and mapping them

I have two tables in MySql Workbench; Categories and Products. I created a third table which contains PK's from the first two tables. How do I sort out which product falls under which category. Do I need to create a fourth table? Also, it is obvious that one category has many products. How do I put this data into the table?
The way I use it in my company is I have a Category table just as you have, a Brands table and a Products table (this is the basic setup, I have more tables for price history, product history, etc).
The Products table is the primary one, containing a foreign key to each of Categories and Brands.
Table tbl_category and tbl_brand has the same structure:
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(100) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
Table tbl_product:
+-----------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| category | int(11) | YES | MUL | NULL | |
| brand | int(11) | YES | MUL | NULL | |
| spec | varchar(100) | YES | | NULL | |
| descript | varchar(1000) | YES | | NULL | |
| unit | varchar(10) | YES | | PÇ | |
| cost | decimal(16,2) | YES | | NULL | |
| ..................................................................|
| |
+-----------+---------------+------+-----+---------+----------------+
And I have the following foreign keys:
KEY `product_category_fk` (`category`),
KEY `product_brand_fk` (`brand`),
CONSTRAINT `product_brand_fk` FOREIGN KEY (`brand`) REFERENCES `tbl_brand` (`id`) ON UPDATE CASCADE,
CONSTRAINT `product_category_fk` FOREIGN KEY (`category`) REFERENCES `tbl_category` (`id`) ON UPDATE CASCADE
The reasoning I used is: any given product has only one category and one brand, so I can put that information in the product record itself.
This is a good example starting point (Taken from here)

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