Yii Database structure - mysql

I'm designing database for Yii web application and I'm not sure I'm doing it right way.
CREATE TABLE user
(
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(128) NOT NULL,
password VARCHAR(128) NOT NULL,
email VARCHAR(128) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE post
(
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL,
description TEXT NOT NULL,
media TEXT NOT NULL,
tag_id INTEGER NOT NULL,
status INTEGER NOT NULL,
create_time INTEGER,
update_time INTEGER,
user_id INTEGER NOT NULL,
CONSTRAINT FK_post_user FOREIGN KEY (user_id)
REFERENCES user (id) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE comment
(
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
content TEXT NOT NULL,
status INTEGER NOT NULL,
create_time INTEGER,
user_id INTEGER NOT NULL,
post_id INTEGER NOT NULL,
CONSTRAINT FK_comment_post FOREIGN KEY (post_id)
REFERENCES post (id) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE tag
(
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(128) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Problems:
1.) In post table I have tag_id. I was thinking to store all existing and newly added tags in tag table and then when someone use already existed tag or made new tag to add as tag_id to post table with ",". Is this the best solution?
2.) In comment table I have user_id and post_id. How I think foreign key are working there should be set 2 foreign keys in comment table? I tried that but got error.
3.) In post table there is media row. I'm going to store in this row location to uploaded image OR embed code from youtube/or any other source. Is this ok to use only same row for that or should I use seperated? 1 for images, 1 for embed code?
Thanks in advance

1) In case I'd use column with name tags instead tag_id where i'd keep serialized array of tag_id's from table tags
2) The problem i think because you tried add foreign keys with same name.
Try to use
CONSTRAINT FK_comment_post FOREIGN KEY
CONSTRAINT FK_comment_post_2 FOREIGN KEY
3) What will be if you'll decide to add another media info in post(pdf_file, or music). Add new column in table post it's not correct. i'd recommend you create additional table postmeta where you can create any type of content, and instead media use post_text. Like in wordpress.

Related

Error code 1215: cannot add foreign key constraint MySQL

I'm having a problem creating a database in MySQL.
The error code:'Error code 1215: cannot add foreign key constraint' pops up when i try to implement my changes. I've paid attention to all the necessary things but i can't find the solution.
This error only happened after i added some tables after having made an initial database(which did work), so hopefully i'm not dealing with this problem throughout the whole project.
Here's a snippet of the code in which the error occurs, the foreign key that's not working correctly is 'tournament_id' referencing to 'id' in tournament:
CREATE DATABASE allin;
USE allin;
CREATE TABLE employee (
phone_number char(12) NOT NULL,
birth_date date NOT NULL,
tournament_id int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(phone_number),
FOREIGN KEY(tournament_id) REFERENCES tournament(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Second table:
CREATE TABLE tournament (
id int NOT NULL AUTO_INCREMENT,
date date NOT NULL,
time time NOT NULL,
cost decimal(5,2) NOT NULL,
min_players int NOT NULL,
min_age int NOT NULL,
max_age int NOT NULL,
location_id int NULL,
winner_id int NULL,
type varchar(40) NULL,
PRIMARY KEY(id),
FOREIGN KEY(winner_id) REFERENCES player(id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY(location_id) REFERENCES event_location(id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The issue is here:
FOREIGN KEY(tournament_id) REFERENCES tournament(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
the above query is of CREATE TABLE employee. In this query, you are creating a FOREIGN KEY that refers to tournament(id), but as of now there is no tournament table exist in the specified database as the tournament table create query is reside below in the sequence.
I layman terms we can say, you are trying to refer a table column that
do not exist.
So to resolve this, run all you parent table creation query first, and than child table.
tournament_id int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(phone_number)
Hey, I don't think you could set another primary key while an "auto increment" already exist

Assign different muliple foreign key in one table from other table in MySQL

I was planning to make 2 tables for user infomation . The first lager table named userInfo has all data . The second smaller table named loginDetails have the minimum data to log in .
My problem is : I could not assign multiple foreign key .
MySQL said:
#1005 - Can't create table `test`.`logindetails` (errno: 150 "Foreign key constraint is incorrectly formed")
Here is code :
CREATE TABLE userInfo
(
userInfoUserNumber INT(255) UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
userInfoUserName VARCHAR(255) UNIQUE NOT NULL,
userInfoPassword VARCHAR(255) NOT NULL,
userInfoFirstName VARCHAR(255) NOT NULL,
userInfoLastName VARCHAR(255) NOT NULL,
userInfoPhoneNumber INT(255) UNSIGNED ZEROFILL UNIQUE NOT NULL,
userInfoPlaceWithoutDivision VARCHAR(255) NOT NULL,
userInfoDivision VARCHAR(255) NOT NULL,
userInfoEmail VARCHAR(255) UNIQUE,
userInfoProfilePicture VARCHAR(255),
PRIMARY KEY (userInfoUserNumber)
);
CREATE TABLE loginDetails
(
loginDetailsUserNumber INT(255) UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
loginDetailsUserName VARCHAR(255) UNIQUE NOT NULL,
loginDetailsPassword VARCHAR(255) NOT NULL,
loginDetailsPhoneNumber INT(255) UNSIGNED ZEROFILL UNIQUE NOT NULL,
loginDetailsEmail VARCHAR(255) UNIQUE,
PRIMARY KEY (loginDetailsUserNumber) ,
FOREIGN KEY (loginDetailsUserName) REFERENCES userInfo(userInfoUserName)
ON DELETE SET NULL
ON UPDATE CASCADE,
FOREIGN KEY (loginDetailsPassword) REFERENCES userInfo(userInfoPassword)
ON DELETE SET NULL
ON UPDATE CASCADE,
FOREIGN KEY (loginDetailsPhoneNumber) REFERENCES userInfo(userInfoPhoneNumber)
ON DELETE SET NULL
ON UPDATE CASCADE,
FOREIGN KEY (loginDetailsEmail) REFERENCES userInfo(userInfoEmail)
ON DELETE SET NULL
ON UPDATE CASCADE
);
[ In short : suppose my first table has 10 columns , my second table has 5 columns , i want to choose any 4 columns from 1st table and copy to my second table ]
Question 2 :
why this statement is error ? please explain
INSERT INTO userInfo(userInfoUserName,userInfoPassword,userInfoFirstName,userInfoLastName,userInfoPhoneNumber,userInfoPlaceWithoutDivision,userInfoDivision)
VALUES (cat,SHA1(cat),white,cat,01111111111,myplace,mydivision);
You can declare a foreign key only if the column you reference is the leftmost column of a key.
Traditionally, you'd reference only a unique or primary key, but InnoDB (strangely) allows a foreign key to reference any kind of key or partial key.
Your column userInfo.userInfoPassword is not part of any key.
It's not clear what purpose there could be for declaring all those foreign keys. If you want them to cascade, to always remain the same value in the userInfo table, then why are they stored in both tables at all? Just store them in one table.
i want to create a different table (loginDetails) taking 4 columns from userinfo
Why? You don't have to create a different table if you want to fetch a result set with just those four columns. You just specify the columns you want in a query instead of using SELECT *.
SELECT loginDetailsUserNumber,
loginDetailsUserName,
loginDetailsPassword,
loginDetailsPhoneNumber,
loginDetailsEmail
FROM userInfo;
Another option would be to use CREATE VIEW to define a view with those four columns, and then you could use SELECT * from your view.
CREATE VIEW loginDetails AS
SELECT loginDetailsUserNumber,
loginDetailsUserName,
loginDetailsPassword,
loginDetailsPhoneNumber,
loginDetailsEmail
FROM userInfo;
SELECT * FROM loginDetails;
When designing foreign key relationships, you should be linking using primary keys. This would suggest:
CREATE TABLE loginDetails (
loginDetailsUserNumber INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
loginDetailsUserInfoUserNumber INT UNSIGNED,
loginDetailsUserName VARCHAR(255) UNIQUE NOT NULL,
loginDetailsPassword VARCHAR(255) NOT NULL,
loginDetailsPhoneNumber INT(255) UNSIGNED ZEROFILL UNIQUE NOT NULL,
loginDetailsEmail VARCHAR(255) UNIQUE,
PRIMARY KEY (loginDetailsUserNumber) ,
FOREIGN KEY (loginDetailsUserInfoUserNumber) REFERENCES userInfo(userInfoUserNumber)
ON DELETE SET NULL
ON UPDATE CASCADE,
);
In other words, you can keep the duplicated columns (perhaps a user changes his/her name or password and you want the version associated with the login). BUT, you should be assigning a user number at login and putting that id in the table.

Error during the creation of table due to foreign key

I have table1 already in my db.
Table1:
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`typename` varchar(255) DEFAULT NULL,
`typecode` varchar(55) DEFAULT NULL,
`parent1` int(11) DEFAULT NULL,
`parent2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `parent1` (`parent1`),
KEY `parent2` (`parent2`)
) ENGINE=InnoDB AUTO_INCREMENT=396 DEFAULT CHARSET=latin1;
I tried to create the second table with foreign key which has reference to product.typename
this is the creation query I have used.
CREATE TABLE measurements (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
age_group varchar(20) NOT NULL,
article_type varchar(255) DEFAULT NULL,
dimension text ,
createdOn int(11) NOT NULL,
updatedOn int(11) NOT NULL,
createdBy text NOT NULL,
foreign KEY(article_type) references product(typename)
)ENGINE=InnoDB AUTO_INCREMENT=396 DEFAULT CHARSET=latin1;
But this table creation is a failure with the following error.
ERROR 1215 (HY000): Cannot add foreign key constraint
I have done show engine innodb\g
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2015-05-15 19:03:28 131f71000 Error in foreign key constraint of table db/measurements:
foreign KEY(article_type) references product(typename)
)ENGINE=InnoDB AUTO_INCREMENT=396 DEFAULT CHARSET=latin1:
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.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
Can some one point me the problem and what is this first columns concept?
Referenced column should be Primary key. Here
foreign KEY(article_type) references product(typename)
you want to reference with typename column which is not PK.
To do it in properly way you should create table ProductType like this:
CREATE TABLE `ProductType` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`typename` varchar(255) DEFAULT NULL,
`typecode` varchar(55) DEFAULT NULL,
) ENGINE=InnoDB AUTO_INCREMENT=396 DEFAULT CHARSET=latin1;
then you can create reference like this:
CREATE TABLE measurements (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
age_group varchar(20) NOT NULL,
IdProductType NOT NULL,
dimension text ,
createdOn int(11) NOT NULL,
updatedOn int(11) NOT NULL,
createdBy text NOT NULL,
foreign KEY(IdProductType) references ProductType(Id)
)ENGINE=InnoDB AUTO_INCREMENT=396 DEFAULT CHARSET=latin1;
Don't forget to do it with Product table.
Above solution is only suggestion, you have to consider your table structure yourself.
A foreign key references a key. This is usually the primary key, but doesn't have to be. In your case however you reference a column (typename) which is not defined as a key. This shows a design flaw.
You decided to use technical IDs as primary keys for your tables. You can do this. But if you do this, keep two things in mind:
You've created IDs in order to link tables easily. So don't reference a record by another column (such as typename), but by its ID.
You must still make sure that the table's natural key is unique.
As to point 2: What is your table's natural key? What is or are the fields that uniquely identify a record (apart from your technically created ID)? Is it typename? Is typename the product's name and must it be unique? Or is this typecode? Whatever it is, give this field a unique constraint, so you cannot have the same product twice in your table.
Maybe it would help you learn to design your database, if you didn't use technical IDs at all. Give it a thought.
Just a side note: Be aware that MySQL has a strange way of using the keyword KEY:
create table t (col int key);
Here KEY really means the table's primary key. col cannot be null and col must be unique. It is short for:
create table t (col int primary key);
However,
create table t (col int, key(col));
is something entirely else. Here, KEY is not short for PRIMARY KEY, but a synonym for INDEX. col can be null, col doesn't have to be unique. So better use the synonym INDEX to make it clear to a reader:
create table t (col int, index(col));
When working with an additional ID, as you are doing, you even need a unique index:
create table t (id int primary key, col int, unique index(col));
or
create table t (id int, col int, primary key(id), unique index(col));

MySQL Cannot Add Foreign Key Constraint

So I'm trying to add Foreign Key constraints to my database as a project requirement and it worked the first time or two on different tables, but I have two tables on which I get an error when trying to add the Foreign Key Constraints.
The error message that I get is:
ERROR 1215 (HY000): Cannot add foreign key constraint
This is the SQL I'm using to create the tables, the two offending tables are Patient and Appointment.
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
CREATE SCHEMA IF NOT EXISTS `doctorsoffice` DEFAULT CHARACTER SET utf8 ;
USE `doctorsoffice` ;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`doctor`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`doctor` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`doctor` (
`DoctorID` INT(11) NOT NULL AUTO_INCREMENT ,
`FName` VARCHAR(20) NULL DEFAULT NULL ,
`LName` VARCHAR(20) NULL DEFAULT NULL ,
`Gender` VARCHAR(1) NULL DEFAULT NULL ,
`Specialty` VARCHAR(40) NOT NULL DEFAULT 'General Practitioner' ,
UNIQUE INDEX `DoctorID` (`DoctorID` ASC) ,
PRIMARY KEY (`DoctorID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`medicalhistory`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`medicalhistory` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`medicalhistory` (
`MedicalHistoryID` INT(11) NOT NULL AUTO_INCREMENT ,
`Allergies` TEXT NULL DEFAULT NULL ,
`Medications` TEXT NULL DEFAULT NULL ,
`ExistingConditions` TEXT NULL DEFAULT NULL ,
`Misc` TEXT NULL DEFAULT NULL ,
UNIQUE INDEX `MedicalHistoryID` (`MedicalHistoryID` ASC) ,
PRIMARY KEY (`MedicalHistoryID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`Patient`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Patient` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`Patient` (
`PatientID` INT unsigned NOT NULL AUTO_INCREMENT ,
`FName` VARCHAR(30) NULL ,
`LName` VARCHAR(45) NULL ,
`Gender` CHAR NULL ,
`DOB` DATE NULL ,
`SSN` DOUBLE NULL ,
`MedicalHistory` smallint(5) unsigned NOT NULL,
`PrimaryPhysician` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`PatientID`) ,
UNIQUE INDEX `PatientID_UNIQUE` (`PatientID` ASC) ,
CONSTRAINT `FK_MedicalHistory`
FOREIGN KEY (`MEdicalHistory` )
REFERENCES `doctorsoffice`.`medicalhistory` (`MedicalHistoryID` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FK_PrimaryPhysician`
FOREIGN KEY (`PrimaryPhysician` )
REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`Appointment`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Appointment` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`Appointment` (
`AppointmentID` smallint(5) unsigned NOT NULL AUTO_INCREMENT ,
`Date` DATE NULL ,
`Time` TIME NULL ,
`Patient` smallint(5) unsigned NOT NULL,
`Doctor` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`AppointmentID`) ,
UNIQUE INDEX `AppointmentID_UNIQUE` (`AppointmentID` ASC) ,
CONSTRAINT `FK_Patient`
FOREIGN KEY (`Patient` )
REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FK_Doctor`
FOREIGN KEY (`Doctor` )
REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`InsuranceCompany`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`InsuranceCompany` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`InsuranceCompany` (
`InsuranceID` smallint(5) NOT NULL AUTO_INCREMENT ,
`Name` VARCHAR(50) NULL ,
`Phone` DOUBLE NULL ,
PRIMARY KEY (`InsuranceID`) ,
UNIQUE INDEX `InsuranceID_UNIQUE` (`InsuranceID` ASC) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`PatientInsurance`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`PatientInsurance` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`PatientInsurance` (
`PolicyHolder` smallint(5) NOT NULL ,
`InsuranceCompany` smallint(5) NOT NULL ,
`CoPay` INT NOT NULL DEFAULT 5 ,
`PolicyNumber` smallint(5) NOT NULL AUTO_INCREMENT ,
PRIMARY KEY (`PolicyNumber`) ,
UNIQUE INDEX `PolicyNumber_UNIQUE` (`PolicyNumber` ASC) ,
CONSTRAINT `FK_PolicyHolder`
FOREIGN KEY (`PolicyHolder` )
REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FK_InsuranceCompany`
FOREIGN KEY (`InsuranceCompany` )
REFERENCES `doctorsoffice`.`InsuranceCompany` (`InsuranceID` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
USE `doctorsoffice` ;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
To find the specific error run this:
SHOW ENGINE INNODB STATUS;
And look in the LATEST FOREIGN KEY ERROR section.
The data type for the child column must match the parent column exactly. For example, since medicalhistory.MedicalHistoryID is an INT, Patient.MedicalHistory also needs to be an INT, not a SMALLINT.
Also, you should run the query set foreign_key_checks=0 before running the DDL so you can create the tables in an arbitrary order rather than needing to create all parent tables before the relevant child tables.
I had set one field as "Unsigned" and other one not. Once I set both columns to Unsigned it worked.
Engine should be the same e.g. InnoDB
Datatype should be the same, and with same length. e.g. VARCHAR(20)
Collation Columns charset should be the same. e.g. utf8
Watchout: Even if your tables have same Collation, columns still could have different one.
Unique - Foreign key should refer to field that is unique (usually primary key) in the reference table.
Try to use the same type of your primary keys - int(11) - on the foreign keys - smallint(5) - as well.
Hope it helps!
Confirm that the character encoding and collation for the two tables is the same.
In my own case, one of the tables was using utf8 and the other was using latin1.
I had another case where the encoding was the same but the collation different. One utf8_general_ci the other utf8_unicode_ci
You can run this command to set the encoding and collation for a table.
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
I hope this helps someone.
To set a FOREIGN KEY in Table B you must set a KEY in the table A.
In table A:
INDEX id (id)
And then in the table B,
CONSTRAINT `FK_id` FOREIGN KEY (`id`) REFERENCES `table-A` (`id`)
I had same problem and the solution was very simple.
Solution : foreign keys declared in table should not set to be not null.
reference : If you specify a SET NULL action, make sure that you have not declared the columns in the child table as NOT NULL. (ref
)
Check following rules :
First checks whether names are given right for table names
Second right data type give to foreign key ?
Please ensure that both the tables are in InnoDB format. Even if one is in MyISAM format, then, foreign key constraint wont work.
Also, another thing is that, both the fields should be of the same type. If one is INT, then the other should also be INT. If one is VARCHAR, the other should also be VARCHAR, etc.
I faced the issue and was able to resolve it by making sure that the data types were exactly matching .
I was using SequelPro for adding the constraint and it was making the primary key as unsigned by default .
Check the signing on both your table columns. If the referring table column is SIGNED, the referenced table column should be SIGNED too.
My problem was that I was trying to create the relation table before other tables!
So you have two ways to fix it:
change the order of MSQL commands
run this before your queries:
SET foreign_key_checks = 0;
NOTE: The following tables were taken from some site when I was doing
some R&D on the database. So the naming convention is not proper.
For me, the problem was, my parent table had the different character set than that of the one which I was creating.
Parent Table (PRODUCTS)
products | CREATE TABLE `products` (
`productCode` varchar(15) NOT NULL,
`productName` varchar(70) NOT NULL,
`productLine` varchar(50) NOT NULL,
`productScale` varchar(10) NOT NULL,
`productVendor` varchar(50) NOT NULL,
`productDescription` text NOT NULL,
`quantityInStock` smallint(6) NOT NULL,
`buyPrice` decimal(10,2) NOT NULL,
`msrp` decimal(10,2) NOT NULL,
PRIMARY KEY (`productCode`),
KEY `productLine` (`productLine`),
CONSTRAINT `products_ibfk_1` FOREIGN KEY (`productLine`) REFERENCES `productlines` (`productLine`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Child Table which had a problem (PRICE_LOGS)
price_logs | CREATE TABLE `price_logs` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`productCode` varchar(15) DEFAULT NULL,
`old_price` decimal(20,2) NOT NULL,
`new_price` decimal(20,2) NOT NULL,
`added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `productCode` (`productCode`),
CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
);
MODIFIED TO
price_logs | CREATE TABLE `price_logs` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`productCode` varchar(15) DEFAULT NULL,
`old_price` decimal(20,2) NOT NULL,
`new_price` decimal(20,2) NOT NULL,
`added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `productCode` (`productCode`),
CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
One additional cause of this error is when your tables or columns contain reserved keywords:
Sometimes one does forget these.
If you are getting this error with PhpMyAdmin, disable foreign key checks before importing the SQL file.
For me the target table was blocking the foreign key.
I had to set Auto-Increment (AI) on the table the Foreign-Key was pointing to.
I had a similar error in creating foreign key in a Many to Many table where the primary key consisted of 2 foreign keys and another normal column. I fixed the issue by correcting the referenced table name i.e. company, as shown in the corrected code below:
create table company_life_cycle__history -- (M-M)
(
company_life_cycle_id tinyint unsigned not null,
Foreign Key (company_life_cycle_id) references company_life_cycle(id) ON DELETE CASCADE ON UPDATE CASCADE,
company_id MEDIUMINT unsigned not null,
Foreign Key (company_id) references company(id) ON DELETE CASCADE ON UPDATE CASCADE,
activity_on date NOT NULL,
PRIMARY KEY pk_company_life_cycle_history (company_life_cycle_id, company_id,activity_on),
created_on datetime DEFAULT NULL,
updated_on datetime DEFAULT NULL,
created_by varchar(50) DEFAULT NULL,
updated_by varchar(50) DEFAULT NULL
);
I had similar error with two foreign keys for different tables but with same key names! I have renamed keys and the error had gone)
Had a similar error, but in my case I was missing to declare the pk as auto_increment.
Just in case it could be helpful to anyone
I got the same error. The cause in my case was:
I created a backup of a database via phpmyadmin by copying the whole database.
I created a new db with the same name the old db had und selected it.
I started an SQL script to create updated tables and data.
I got the error. Also when I disabled foreign_key_checks. Altough the database was completely empty.
The cause was: Since i used phpmyadmin to create some foreign keys in the renamed database - the foreign keys where created with a database name prefix but the database name prefix was not updated. So there were still references in the backup-db pointing to the newly created db.
My solution is maybe a little embarrassing and tells the tale of why you should sometimes look at what you have in front of you instead of these posts :)
I had ran a forward engineer before, which failed, so that meant that my database already had a few tables, then i have been sitting trying to fix foreign key contraints failures trying to make sure that everything was perfect, but it ran up against the tables previously created, so it was to no prevail.
In my case, there was a syntax error which was not explicitly notified by MySQL console upon running the query. However, SHOW ENGINE INNODB STATUS command's LATEST FOREIGN KEY ERROR section reported,
Syntax error close to:
REFERENCES`role`(`id`) ON DELETE CASCADE) ENGINE = InnoDB DEFAULT CHARSET = utf8
I had to leave a whitespace between REFERENCES and role to make it work.
For me it was - you can't omit prefixing the current DB table if you create a FK for a non-current DB referencing the current DB:
USE currrent_db;
ALTER TABLE other_db.tasks ADD CONSTRAINT tasks_fk FOREIGN KEY (user_id) REFERENCES currrent_db.users (id);
If I omit "currrent_db." for users table, I get the FK error. Interesting that SHOW ENGINE INNODB STATUS; shows nothing in this case.
My Solution!!
If we want to have column1 of table1 as a foreign key of table2, then column1 should be a key of table1.
For example, consider we have departments table, which has dept_id column.
Now let's say we have another table named employees which has emp_dept_id column.
If we want to use the dept_id column of the department table as a foreign key for the emp_dept_id column of emp, then the dept_id of department table SHOULD ATLEAST BE a key if not a primary key.
So make sure that dept_id of depratment is either a primary key or a unique key before using it as a foreign key for another table.
I had this same issue then i corrected the Engine name as Innodb in both parent and child tables and corrected the reference field name
FOREIGN KEY (c_id) REFERENCES x9o_parent_table(c_id)
then it works fine and the tables are installed correctly. This will be use full for someone.

Database design MySQL using foreign keys

I'm having some a little trouble understanding how to handle the database end of a program I'm making. I'm using an ORM in Kohana, but am hoping that a generalized understanding of how to solve this issue will lead me to an answer with the ORM.
I'm writing a program for users to manage their stock research information. My tables are basically like so:
CREATE TABLE tags(
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
tags VARCHAR(30),
UNIQUE(tags)
)
ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE stock_tags(
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
tag_id INT NOT NULL,
stock_id INT NOT NULL,
FOREIGN KEY (tag_id) REFERENCES tags(id),
FOREIGN KEY(stock_id) REFERENCES stocks(id) ON DELETE CASCADE
)
ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE notes(
id INT AUTO_INCREMENT NOT NULL,
stock_id INT NOT NULL,
notes TEXT NOT NULL,
FOREIGN KEY (stock_id) REFERENCES stocks(id) ON DELETE CASCADE,
PRIMARY KEY(id)
)
ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE links(
id INT AUTO_INCREMENT NOT NULL,
stock_id INT NOT NULL,
links VARCHAR(2083) NOT NULL,
FOREIGN KEY (stock_id) REFERENCES stocks(id) ON DELETE CASCADE,
PRIMARY KEY(id)
)
ENGINE=INNODB DEFAULT CHARSET=utf8;
How would I get all the attributes of a single stock, including its links, notes, and tags? Do I have to add links, notes, and tags columns to the stocks table and then how do you call it? I know this differs using an ORM and I'd assume that I can use join tables in SQL.
Thanks for any help, this will really help me understand the issue a lot better.
You will have to link the tables together using JOINS
Something like
SELECT *
FROM stocks s INNER JOIN
stock_tags st ON s.id = st.stock_id INNER JOIN
tags t ON st.tag_id = t.id etc...