Error on creating foreign key relationship between non-primary key - mysql

I have two table
CREATE TABLE `abc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ref_id` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ref_id_UNIQUE` (`ref_id`)
)
CREATE TABLE `xyz` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ref_id` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ref_id_UNIQUE` (`ref_id`)
)
I want to make foreign key relation ship between xyz's ref_id and abc's ref_id .But Mysql gives error 1215.

You should make the foreign key relationships to the primary keys. I know that MySQL allows foreign key relationships to anything with an index. But the correct practice is to use primary keys.
So declare the table like this:
CREATE TABLE `xyz` (
`id` int(11) NOT NULL AUTO_INCREMENT,
abc_id int DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ref_id_UNIQUE` (`abc_id`),
ADD CONSTRAINT fk_xyz_abc FOREIGN KEY (abc_id) REFERENCES abc(id)
);
If you want the ref_id for an xyz row, then use JOIN to get the information.

Take a look at Gordon Linoff's answer, his suggestion makes sense, even though it does not answer the question. So what can cause an error when you intend to create a foreign key relationship? The obvious possibility is syntax error and typo, so you will need to check against those and fix any such problems.
Another possibility is that you have inconsistency, that is, you try to create a foreign key constraint in one of your tables, but not all the values have exact matches. So, assuming that you have Foo and Bar table and you intend Foo.lorem to be a foreign key referencing Bar.ipsum, then you will need to ensure that all the values you have for Foo.lorem has a Bar.ipsum pair with the exact same values (except null). If that's not true, then your foreign key constraint will not be successfully created. Find such inconsistencies:
select distinct Foo.lorem
from Foo
where not (Foo.lorem is null) and
not exists (select 1 from Bar where Foo.lorem = Bar.ipsum);
Read the lines carefully and make sure you fix any such Foo.lorem values.

Related

cannot add foreign key constraint in phpmyadmin

While creating 2 tables in phpmyadmin I am getting an error like this.
MySQL said: Documentation
#1215 - Cannot add foreign key constraint
My table structures are
CREATE TABLE `iwd_storelocator_manufacturer` (
`entity_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` varchar(255) NOT NULL ,
`code` varchar(255) NOT NULL ,
`grayscale_image` varchar(255) NULL ,
`color_image` varchar(255) NULL ,
PRIMARY KEY (`entity_id`)
);
CREATE TABLE `iwd_storelocator_manufacturer_to_store` (
`manufacturer_id` int(11) UNSIGNED NOT NULL ,
`store_id` int(11) NOT NULL ,
`preferred` int NULL ,
PRIMARY KEY (`manufacturer_id`, `store_id`),
FOREIGN KEY (`store_id`) REFERENCES `iwd_storelocator_store` (`store_id`) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY (`manufacturer_id`) REFERENCES `iwd_storelocator_manufacturer` (`entity_id`) ON DELETE RESTRICT ON UPDATE CASCADE
);
Can you tell me whats the problem in it?
This is my iwd_storelocator_store table
iwd_storelocator_store
In order to know exactly what is wrong, you must check in LATEST FOREIGN KEY ERROR section.
Use this query to find this out:
SHOW ENGINE INNODB STATUS
Also, make sure that all the data types are the same: the data type of the child column must match the data type from the parent column.
If the problem is the order of creation of the tables (which can cause this error), just run set foreign_key_checks=0 so you can create the tables in any order rather than having to create all the parents tables BEFORE the child tables.
Finally, make sure that the encoding is the same for all the tables.
EDIT: in your case, you should also give us the structure of iwd_storelocator_store table
Now that we have your iwd_storelocator_store table, I think that you should create an index on store_id column as it is not the primary key of the table

Odd Error in mariaDB Foreign Keys

Hi i hope some one can help my problem is that when i try to add a foreign key constraint i get this error.
My database name is "hazard"
Child:
CREATE TABLE `child` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`a` INT(11) NULL DEFAULT NULL,
`b` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
Parent:
CREATE TABLE `parent` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`alfa` INT(11) NULL DEFAULT NULL,
`beta` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
Those are the create codes (using HeidiSQL)
and when i try to add a foreign key
with
ALTER TABLE CHILD MODIFY COLUMN A INT,add constraint fk_parent_child FOREIGN KEY(A) REFERENCES PARENT(ALFA);
or
ALTER TABLE CHILD add constraint fk1 foreign key (a) references parent(alfa);
I get the same error
Can't create table 'hazard.#sql-d04_53' (errno: 150)
this is happening to many of my classmates using MariaDB and mySQL
Beforehand an apology for the inconvenience and I hope you guys can help us.
Add
KEY (`alfa`)
to the parent table. "The referenced columns must be a PRIMARY KEY or a UNIQUE index." – https://mariadb.com/kb/en/mariadb/foreign-keys/
http://sqlfiddle.com/#!9/b4c12
Error 150 usually means you are updating the tables in the wrong order. That is, your first INSERT violates the FOREIGN KEY constraint that your second INSERT will fix.
In your case you are doing ALTER instead of INSERT. Swap the order of the ALTERs. If that does not work, check the data to see that you won't be violating FK constraints. If you get past that, read on...
In extreme cases, you can turn off foreign key constraints while doing the inserts, then turn them back on. (But that leaves you vulnerable to screw-ups.)

How to code a foreign key in sql?

Hi this is the table I am trying to create:
CREATE TABLE images
(
id PRIMARY KEY NOT NULL INT,
product_id FOREIGN KEY NOT NULL INT,
src varchar(255) NOT NULL
)
But its not letting me (I am getting a syntax error). Anyone have any ideas?
CREATE TABLE IMAGES(
Id int NOT NULL,
PRODUCT_ID int NOT NULL,
src varchar(255) NOT NULL,
PRIMARY KEY (Id),
FOREIGN KEY (P_Id) REFERENCES PRODUCTS(P_Id)
)
and make sure you build the Products table first , and do the reference foreign key
Check out InnoDB Foreign Key Constraints for the right syntax to use. In particular, you need to declare the column you're referencing when you create a foreign key.
Additionally, since you're using MySQL, make sure your tables use InnoDB, otherwise the foreign keys won't actually get enforced.

Foreign key between MySQL InnoDB tables not working...why?

I have the following tables:
specie (MyIsam)
image (InnoDB)
specie_map (InnoDB)
The specie_map table should map an image to a specie, and therefore has the following columns:
specie_id
image_id
Both are int 11, just like the id columns of the specie and image tables. I know I can't create a foreign key between specie_id and specie=>id, since the specie table is a MyIsam table. However, I would expect it to be possible to create a foreign key between image_id and image=>id.
I can create that foreign key and it will save it, however, the CASCADE action I have associated with it does not work. When I delete an image, it does not delete the specie_map entry that is associated with it. I would expect this to work, as this foreign key is between InnoDB tables. Both columns are indexed and of the same data type.
Is this a limitation of MySQL, or am I doing something else wrong?
Update: as requested hereby the table definitions. I have snipped unimportant columns:
-- ----------------------------
-- Table structure for `image`
-- ----------------------------
DROP TABLE IF EXISTS `image`;
CREATE TABLE `image` (
`id` int(11) NOT NULL auto_increment,
`guid` char(36) default NULL,
`title` varchar(255) NOT NULL,
`description` text,
`user_id` int(11) NOT NULL,
`item_id` int(11) default NULL,
`date_uploaded` timestamp NOT NULL default '0000-00-00 00:00:00',
`date_created` timestamp NOT NULL default '0000-00-00 00:00:00',
`date_modified` timestamp NOT NULL default '0000-00-00 00:00:00',
`status` enum('softdeleted','tobedeleted','active') default 'active',
PRIMARY KEY (`id`),
KEY `image_user` (`user_id`),
KEY `image_item` (`item_id`),
KEY `image_mod_by` (`moderated_by`),
CONSTRAINT `image_mod_by` FOREIGN KEY (`moderated_by`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `image_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='stores image data (not file data)';
-- ----------------------------
-- Table structure for `specie`
-- ----------------------------
DROP TABLE IF EXISTS `specie`;
CREATE TABLE `specie` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(256) NOT NULL,
`commonname` varchar(256) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- ----------------------------
-- Table structure for `specie_map`
-- ----------------------------
DROP TABLE IF EXISTS `specie_map`;
CREATE TABLE `specie_map` (
`id` int(11) NOT NULL auto_increment,
`image_id` int(11) NOT NULL,
`specie_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`karma` int(11) NOT NULL,
`date_created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `image_id` (`image_id`),
KEY `specie_id` (`specie_id`),
CONSTRAINT `specie_map_ibfk_1` FOREIGN KEY (`image_id`) REFERENCES `image` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Foreign keys works only with InnoDb in mysql. MyISAM doesn't support them (the statements are ignored).
And is there any reason why you mix multiple DB engines?
I think you should post the exact DDL statements you used when you attempted to create these tables and the foreign key. Foreign keys between innodb tables work fine, but there are still a few things to look out for:
0) Both tables must be InnoDB. This was already highlighted by the other posters and this is probably the immediate cause of your problem.
1) the data type of the referencing columns (those that make up the foreign key) and their respective referenced columns should be the same. For example, you can't create a foreign key constrain on an INT UNSIGNED column to a plain INT column.
2) if the foreign key is created as part of the table DDL, be sure to put the foreign key definition in the constraints section, that is, below all column definitions. For example:
CREATE TABLE parent (
id int unsigned PRIMARY KEY
);
CREATE TABLE child (
parent_id int unsigned
, foreign key (parent_id)
references parent (id)
);
will work but this:
CREATE TABLE child (
parent_id int unsigned
foreign key references parent (id)
);
won't. It will fail silently because MySQL's parser ignores these types of constraint definitions even before InnoDB gets to create the table (silly, but that's how it is)
3) There must be an index over all the referenced columns. Usually the referenced columns will together make up a primary key or a unique constraint anyway, but it is your job to define this before defining the foreign key.
Final word of advice: if you think your DDL is ok but you still get an error when you execute it, for example like this:
ERROR 1005 (HY000): Can't create table 'test.child' (errno: 150)
Warning (Code 150): Create table 'test/child' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
Error (Code 1005): Can't create table 'test.child' (errno: 150)
Then these errors may still not reveal the true nature of the error (silly again, but that's how it is). To shed more light on it, run this command immediately after your attempt to create the foreign key:
SHOW ENGINE INNODB STATUS;
This will give you a bunch of status info, and one section there looks like this:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
120122 11:38:28 Error in foreign key constraint of table test/child:
foreign key (parent_id) references parent (id) ):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
As you can see, this gives a bit more information and reveals the true problem, namely "column types in the table and the referenced table do not match for constraint"
So please, post your actual DDL, I'm sure there is a problem in there somewhere.

database design: User will submit a howto, each howto will have one or more steps associated with, each step can have random pictures associated with

I am trying to design a database but I need some help with the relationships. Am i getting the table design right?
Here is the database idea..
User will submit a howto, each howto will have one or more steps associated with(a one to many). each step can have random pictures associated with(another one to many). so I am thinking of this:
CREATE TABLE `HowtoStepImage`
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL,
`howto_id` varchar(25) NOT NULL,
`step_id` varchar(25) NOT NULL,
`img_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `hsi_k_1` (`howto_id`),
CONSTRAINT `hsi_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `hsi_ibfk_2` FOREIGN KEY (`step_id`) REFERENCES `HowtoStep` (`step_id`),
CONSTRAINT `hsi_ibfk_3` FOREIGN KEY (`img_id`) REFERENCES `StepImage` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
table HowtoStep
step_id, title, content, created
primary key (step_id)
table StepImage
img_id, filename, created
CREATE TABLE `UserHowtoComment` (
`id` int(10) unsigned NOT NULL auto_increment,
`howto_id` varchar(25) NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`comment` varchar(500) NOT NULL,
`created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `UserHowtoComment_ibfk_1` (`howto_id`),
KEY `UserHowtoComment_ibfk_2` (`user_id`),
CONSTRAINT `UserHowtoComment_ibfk_1` FOREIGN KEY (`howto_id`) REFERENCES `HowtoStepImage` (`howto_id`),
CONSTRAINT `UserHowtoComment_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
however, I am getting error when creating the table, I am sure it is due to my database design. here is what mysql>SHOW ENGINE INNODB STATUS; shows:
091217 9:59:59 Error in foreign key constraint of table UserhowtoComment:
FOREIGN KEY (`howto_id`) REFERENCES `howtoStepImage` (`howto_id`),
CONSTRAINT `UserHowtoComment_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
the howto_id is a key(index) in UserHowtoComment though. I am not sure if that is the exact problem here..
Make 3 tables: one for HowTo, one for HowToStep, one for HowToStepImage.
Give each table a clearly defined key, e.g. a number or a string.
Then let the 'child' table refer to the key of the parent table.
Make sure that the columns have clear names as well.
TABLE HowTo
COLUMNS HowToId(key)
TABLE HowToStep
COLUMNS HowToStepId(key), HowToId
TABLE HowToStepImage
COLUMNS HowToStepImageId(key), HowToStepId
your query is really messy e.g. step_id varchar(25) needs to be an int.
why dont you just use a gui programm or maybe the good old phpMyAdmin, so you can learn the from the Querys they are creating, phpMyAdmin also has a advanced feature call "Designer" to create constraints.
If I read this correctly, your HowToComment id is a foreign key to HowtoStepImage. Does every comment have to have an image? Seems like a chicken and the egg issue. It seems, from your problem description, that an image links to a comment, not the other way around.
you're falling prey to the misleading terminology in MySQL. in the relational model, key is (necessarily) distinct. in the MySQL-speak, it's just an index. you need either PRIMARY KEY or UNIQUE KEY.
edit to add explicitly what is implied above: foreign keys must point to a key in the relational sense.