I'm trying to add a foreign key to my user table.
All of my tables are InnoDB, and are using the same charset. I've got not idea as to why it isn't working :(.
Here is a screenshot of the user table:
As you can see, my userid, is an integer with the max length of 10.
This is the second table (called Content Enabled):
userid, in Content enabler, is identical to the userid in the users table, except it's not a primary index.
When I want to link them via a foreign key, using this query:
ALTER TABLE `contentenabler` ADD FOREIGN KEY ( `userid` ) REFERENCES `tietgen`.`users` (
`userid`
) ON DELETE CASCADE ON UPDATE CASCADE ;
This returns the error Error creating foreign key on userid (check data types)
As far as I can see, the data type are the same, where am I going wrong?
userid is UNSIGNED in your users table, but not your other table.
Related
I have two tables: Message and Product.
In the Message table, there is a sourceid, which is equal to ProductId under table Product.
A Product is given a product id (productID), and a user can message the seller regarding the product. And for those messages, if they are related to certain product than they are given a sourceid, which is basically the product id. If the message is not related to any product, the sourceid will be set as 0.
I am able to set a foreign key constrain to delete the message entry whenever a seller delete a product, all related messages will be deleted.
However, I found that all message that is not related to a product, with sourceid set as 0, are not saving in the database. Obviously, because there is not a product with a productid = 0, and that the foreign key constraint will delete the message entry (with sourceid = 0) immediately.
Is there a way to set condition in phpmyadmin? If I can set that if the foreign key constraint only execute when sourceid > 0, then the system should work out. But I am not sure how to set this condition, or if phpmyadmin allow to set this condition.
Please help. Thank you so much.
Yes, if the foreign key is not relevant to some messages, make the product_id foreign key column be nullable. Store NULL instead of 0 when you don't want to reference any product. The NULL is ignored for purposes of the foreign key reference.
This is virtually the same as these past questions I answered:
MySQL foreign key to allow NULL? (2009)
Foreign key or null value (2011)
You can define the Message table with a foreign key using ON DELETE CASCADE:
CREATE TABLE Message (
messageid INT(11) NOT NULL AUTO_INCREMENT,
message VARCHAR(255) NOT NULL,
-- other columns
sourceid INT(11) NOT NULL,
PRIMARY KEY (messageid),
FOREIGN KEY (sourceid) REFERENCES Product(ProductId) ON DELETE CASCADE
) ENGINE=InnoDB;
If you don't want to redefine the entire table, you can use the following ALTER TABLE statement:
ALTER TABLE Message
ADD CONSTRAINT fk_pid
FOREIGN KEY (sourceid)
REFERENCES Product (ProductId)
ON DELETE CASCADE
With this change in place, deleting a product record from the Product table will cause all its corresponding messages in Message to also be deleted.
I am in the middle of migrating an old (unnormalized) database to its new version.
Right now I have this intermediate result:
CREATE TABLE recipient(
id int NOT NULL AUTO_INCREMENT,
email VARCHAR(255),
PRIMARY KEY (id),
UNIQUE INDEX (`email`),
) ENGINE=INNODB;
CREATE TABLE comment(
# Right now this is always NULL:
fk_recipient INT,
# Temporary solution. Note that this field is NOT UNIQUE:
tmp_email VARCHAR(255) NOT NULL,
# ...
FOREIGN KEY (`fk_recipient`) REFERENCES recipient(id);
) ENGINE=INNODB;
Both tables are filled with correct data:
some million comments with the right tmp_email and fk_recipient = null in table comment (note: emails are not unique)
some hundred thousand UNIQUE email adresses in table recipient.
What I need to do:
I want to get rid of the comment.tmp_email column and instead point comment.fk_recipient to the appropriate row in table recipient.
My current approach (using PHP):
get all comments
iterate over all comments:
look up the right row in recipient table
set right foreign key
... DROP COLUMN tmp_email
This takes forever and made me wonder if there is no native MySQL way to do that?
The following workaround will do the job:
Create temporary foreign key on comment.tmp_email:
ALTER TABLE comment
ADD CONSTRAINT `tmpMailKey` FOREIGN KEY (`tmp_email`)
REFERENCES `recipient`(`email`);
Join the two tables on the temporary key and use the information to set the real foreign key:
UPDATE comment c
INNER JOIN recipient r
ON
c.tmp_email = r.email
AND c.tmp_email IS NOT NULL
SET c.fk_recipient = r.id;
Get rid of temporary foreign key (and the tmp column too):
ALTER TABLE `udw_v3`.`travelogue_guestbookentry`
DROP COLUMN `tmp_email`,
DROP INDEX `tmpMailKey`,
DROP FOREIGN KEY `tmpMailKey`;
I have two tables as follow:
1st Table:
CREATE TABLE User (
User_ID VARCHAR(8)NOT NULL PRIMARY KEY,
User_Name VARCHAR (25) NOT NULL,
User_Gender CHAR (1) NOT NULL,
User_Position VARCHAR (10) NOT NULL,
);
2nd table:
CREATE TABLE Training (
Training_Code VARCHAR(8) NOT NULL Primary Key,
Training_Title VARCHAR(30) NOT NULL,
);
I am trying to create a table which has two foreign keys to join both of the previous tables:
CREATE TABLE Request (
User_ID VARCHAR(8) NOT NULL,
Training_Code VARCHAR(8) NOT NULL,
Request_Status INT(1) NOT NULL
);
When I am trying to set the foreign keys in the new table, the User_ID can be done successfully but the Training_Code cannot be set to foreign key due to the error:
ERROR 1215 (HY000): Cannot add foreign key constraint
As I searched for this problem, the reason for it, is that data type is not the same, or name is not the same.. but in my situation both are correct so could you tell me what is wrong here ?
You need an index for this column in table Request too:
Issue first
CREATE INDEX idx_training_code ON Request (Training_Code);
Then you should be successful creating the foreign key constraint with
ALTER TABLE Request
ADD CONSTRAINT FOREIGN KEY idx_training_code (Training_Code)
REFERENCES Training(Training_Code);
It worked for me. But I've got to say that it worked without create index too, as the documentation of Using FOREIGN KEY Constraints states:
MySQL requires indexes on foreign keys and referenced keys so that
foreign key checks can be fast and not require a table scan. In the
referencing table, there must be an index where the foreign key
columns are listed as the first columns in the same order. Such an
index is created on the referencing table automatically if it does not
exist. This index might be silently dropped later, if you create
another index that can be used to enforce the foreign key constraint.
index_name, if given, is used as described previously.
Emphasis by me. I don't know what's the issue in your case.
Demo
Explanation of the issue
The behavior mentioned in the question can be reproduced if the table Training is using the MyISAM storage engine. Then creating a foreign key referencing the table Training will produce the mentioned error.
If there's data in the table, then simple dropping of the table would not be the best solution. You can change the storage engine to InnoDB with
ALTER TABLE Training Engine=InnoDB;
Now you can successfully add the foreign key constraint.
MySQL Workbench came up with the following SQL to create a table:
CREATE TABLE IF NOT EXISTS `mydb`.`errors_reports` (
`error_id` INT NOT NULL ,
`report_short` VARCHAR(15) NOT NULL ,
PRIMARY KEY (`error_id`, `report_short`) ,
INDEX `error_id_idx` (`error_id` ASC) ,
INDEX `report_short_idx` (`report_short` ASC) ,
CONSTRAINT `error_id`
FOREIGN KEY (`error_id` )
REFERENCES `mydb`.`errors` (`error_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `report_short`
FOREIGN KEY (`report_short` )
REFERENCES `mydb`.`reports` (`report_short` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
which looks fine to me, and there are a bunch of other very similar tables in my database which MySQL was perfectly happy to create.
But this one...
ERROR 1022 (23000): Can't write; duplicate key in table 'errors_reports'
I can't for the life of me see any duplicate keys here. There's only one key defined!
I'm running MySQL 5.6 with a fresh default install. There's nothing in the error log.
Ideas?
Edit: through a process of elimination (going back to the simplest possible definition of the table, then gradually adding bits back in) the problem appears to be this bit:
CONSTRAINT `error_id`
FOREIGN KEY (`error_id` )
REFERENCES `mydb`.`errors` (`error_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
which is particularly odd as there is identical code in several other table definitions and those are perfectly okay!
The problem is that the name of a foreign key can not be the same as another foreign key in the entire model.
Imagine this situation
Catalog --> Supplier
Product --> Supplier
if the name of the foreign key in table Catalog for supplier is "supplier" and you assigned the same name in product table then the foreign keys names will "collide".
You need to name them differently..
For example:
catalog_supplier
product_supplier
It seems you're creating an index on the foreign key columns. When creating a foreign key in InnoDb, one will be created automatically.
See this thread.
Try using INSERT IGNORE instead of INSERT where INSERT IGNORE will not insert a new row if a duplicate primary key is found. This should help resolve the problem temporary but I would recommend truncating the table.
I wish to have a foreign key in a table but I have no idea how to do it. I wish have a UserID Column in the "wall" table so that I can link back and get the userid's details etc. How would i go about doing this?
Wall Table:
alt text http://img821.imageshack.us/img821/7701/screenshot20100808at010.png
Users Table:
alt text http://img375.imageshack.us/img375/7701/screenshot20100808at010.png
1) In order to have a foreign key column called userid in the WALL table, you need to create the column - skip to #2 if the column already exists:
ALTER TABLE WALL
ADD COLUMN userid INT(25) NOT NULL
If you want to allow WALL records to exist without the userid being specified:
ALTER TABLE WALL
ADD COLUMN userid INT(25) NULL
2) Now you add the foreign key constraint:
ALTER TABLE WALL
ADD FOREIGN KEY (userid) REFERENCES USERS(userid)
Add a UserID column to the Wall table and then create a foreign key on it. In SQL, it'd look like this:
CREATE TABLE Wall (
...
UserID INT,
...
FOREIGN KEY (UserID) REFERENCES User (UserID) ON UPDATE CASCADE ON DELETE RESTRICT,
...
) ENGINE=InnoDB;
Note that you may not want to have ON DELETE RESTRICT. That's the most restrictive option. Read up about it on the MySQL website: http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html