MySQL Can't create table (errno: 150) - mysql

I have the following two tables:
CREATE TABLE `table1` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`CODE` varchar(30) COLLATE utf8_bin NOT NULL,
`LANG` varbinary(30) NOT NULL,
`NAME` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`ID`),
KEY `NewIndex1` (`CODE`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
and
CREATE TABLE `table2` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`TABLE1_CODE` varchar(30) NOT NULL,
`SOME_ADD` varchar(30) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
and I am trying to make a reference with:
alter table `factorydb`.`table2` add constraint `FK_table2` FOREIGN KEY (`TABLE1_CODE`) REFERENCES `table1` (`CODE`)
I get the error:
Can't create table 'factorydb.#sql-70c_306' (errno: 150)
The idea is to deal with language entries in my tables, so that I will have some values in table1 as
ID | CODE | LANG | NAME
1 CARCODE EN Car
2 CARCODE DE Auto
And I want to make a reference to the CODE in table1 as for me both CARCODE values are valid, only depending on the language settings.
I am doing it wrong?
All help is appreciated.

Both the columns in the foreign key, must be the same type, length AND collation.
Btw, you really want to prefer setting a foreign key on integers instead of varchars, it's much faster joining and takes less space

The problem is that the two linked columns are not the same type:
Table1
---------
`CODE` varchar(30) COLLATE utf8_bin NOT NULL,
Table2
---------
`SOME_ADD` varchar(30) DEFAULT NULL,
//This column does not have the utf8_bin collation !
You need to make sure the definition is exactly the same.

Change your FK column like
TABLE1_CODE varchar(30) COLLATE utf8_bin NOT NULL

Related

MYSQL - foreign key varchar column

I would like to add localization to my database. I created languages table and I would like to add foreign key to user table:
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`name` varchar(30) NOT NULL,
`email` varchar(100) NOT NULL,
`password` varchar(60) DEFAULT NULL,
`registrationDate` datetime DEFAULT current_timestamp(),
`lastLoginDate` datetime DEFAULT NULL,
`isConfirmed` tinyint(1) NOT NULL DEFAULT 0,
`activationKey` varchar(32) NOT NULL,
`resendEmail` tinyint(1) DEFAULT NULL,
`subscribedNews` tinyint(1) NOT NULL DEFAULT 1,
`activated` tinyint(1) DEFAULT 1,
`lang` varchar(5) NOT NULL DEFAULT 'en'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `users`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `email` (`email`);
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
create table languages(
code varchar(5) primary key,
name varchar(255) not null,
dateFormat varchar(255),
dateTimeFormat varchar(255),
currency varchar(255)
);
ALTER TABLE users
ADD lang varchar(5) NOT NULL DEFAULT 'cs';
ALTER TABLE users ADD CONSTRAINT fk_user_lang FOREIGN KEY (lang) REFERENCES languages(code);
I can't add foreign key on lang column:
error code: 150 "Foreign key constraint is incorrectly formed"
Why I can't create varchar foreign key. I would not add int primary key in languages table, because, I would like to get data from database as /api/users/cs instead of /api/users?lang=1.
Thanks
You didn't specify the character set or collation for the languages table.
Whereas users is explicitly utf8, you might be using a MySQL version where the default charset is utf8mb4 or a very old version where the default charset is latin1.
Double-check with:
SHOW CREATE TABLE languages\G
That will display the charset and collation for that table. It must be the same as the charset and collation for the foreign key column in users.
If you change the default character set of the table languages to utf8, which you defined for the table users, then it will work:
ALTER TABLE languages CONVERT TO CHARACTER SET utf8;
See the demo.

MySQL InnoDB FOREIGN KEY ERROR

I have the followiing tables:
CREATE TABLE `Atletica` (
`Universidade` varchar(100) NOT NULL,
`Nome` varchar(100) NOT NULL,
`Logo` varchar(100) NOT NULL,
`GritoDeGuerra` varchar(100) NOT NULL,
`EnderecoCEP` int(11) NOT NULL,
`EnderecoNumero` int(11) NOT NULL,
`MedalhaOuro` int(6) NOT NULL,
`MedalhaPrata` int(6) NOT NULL,
`MedalhaBronze` int(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Table structure for table `Endereco`
--
CREATE TABLE `Endereco` (
`Rua` varchar(50) NOT NULL,
`Numero` int(11) NOT NULL,
`Bairro` varchar(50) DEFAULT NULL,
`CEP` int(11) NOT NULL,
`Cidade` varchar(50) NOT NULL,
`Estado` varchar(50) NOT NULL,
`Complemento` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `Atletica`
--
ALTER TABLE `Atletica`
ADD PRIMARY KEY (`Universidade`,`Nome`),
ADD KEY `EnderecoCEP` (`EnderecoCEP`),
ADD KEY `EnderecoNumero` (`EnderecoNumero`);
--
-- Indexes for table `Endereco`
--
ALTER TABLE `Endereco`
ADD PRIMARY KEY (`Numero`,`CEP`);
And I keep getting the error:
Error creating foreign key on EnderecoCEP, EnderecoNumero (check data types)
when I try to execute the following command:
ALTER TABLE `Atletica`
ADD FOREIGN KEY (`EnderecoCEP`, `EnderecoNumero`)
REFERENCES `proj3`.`Endereco`(`CEP`, `Numero`)
ON DELETE RESTRICT ON UPDATE RESTRICT;
Ive read tons of similar questions here but all of them the error was an obvious data type mismatch. I only have those two table on my database. Please help.
Thank you very much for your time.
As it turns out, when you create a foreign key with multiple columns, it should be in the same order ar the primary key in the referencing table.

Troubleshooting unmatched foreign keys in mysql tables

I have two myIsam tables student and fee which were later changed into InnoDB engine and assigned foreign key to section field in fee table which points to section field in student table with UPDATE and DELETE CASCADE. My problem is that the existing section field values does not match with the existing student section values. This happened because before I had changed my engine, I had updated student table section field, and thought that section field values in fee table would also changed when I converted both the tables and assigned foreign keys to section field in both the tables. I am not sure whether synchronization will solve it. I am newbie and have no idea how I would solve this. Please help me.
Fee table:
CREATE TABLE IF NOT EXISTS `fee` (
`f_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`regd` bigint(20) unsigned NOT NULL,
`Class` varchar(20) COLLATE latin1_general_ci NOT NULL,
`Section` varchar(10) COLLATE latin1_general_ci NOT NULL,
`Amount` int(11) NOT NULL,
`Balance` int(11) NOT NULL,
PRIMARY KEY (`f_id`),
KEY `Section` (`Section`),
KEY `Rollno` (`Rollno`),
KEY `regd` (`regd`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
AUTO_INCREMENT=2500;
ALTER TABLE `fee`
ADD CONSTRAINT `fee_ibfk_1` FOREIGN KEY (`Section`)
REFERENCES `student` (`Section`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `fee_ibfk_2` FOREIGN KEY (`Rollno`)
REFERENCES `student` (`Roll_no`) ON DELETE CASCADE ON UPDATE CASCADE;
Student Table:
CREATE TABLE IF NOT EXISTS `student` (
`regd` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE latin1_general_ci NOT NULL,
`Date_of_birth` date NOT NULL,
`Sex` varchar(20) COLLATE latin1_general_ci NOT NULL,
`Roll_no` int(11) DEFAULT NULL,
`Section` varchar(20) COLLATE latin1_general_ci DEFAULT NULL,
PRIMARY KEY (`regd`),
KEY `Section` (`Section`),
KEY `Roll_no` (`Roll_no`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
AUTO_INCREMENT=2500;
Unless you have some record of which fee should point to which student, I'm afraid you can't do this.
You'll have to recreate the links; either using logs of which UPDATEs you ran, from a backup or manually.

MYSQL #1005 - Can't create table (errno: 150)

CREATE TABLE IF NOT EXISTS `userinit` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`usn` varchar(20) NOT NULL,
`pwd` varchar(20) NOT NULL,
`cmnd` int(9) NOT NULL,
`dienthoai` varchar(11) NOT NULL,
PRIMARY KEY (`id`,`usn`,`cmnd`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
This is the first table i've created in mysql, then i make a query to create my second table userinfo, below
create table userinfo(
cmnd int(9) primary key not null,
ngaycapcmnd date,
noicap varchar(50) character set utf8,
hoten varchar(50) character set utf8 not null,
ngaysinh date not null,
quequan varchar(50) character set utf8,
diachi varchar(100) character set utf8 not null,
email varchar(100) unique not null,
constraint fk_userinfo_userinit foreign key (cmnd) references userinit(cmnd)
)
Then it says when i press OK: #1005 - Can't create table 'xbook.userinfo' (errno: 150).
I use the lastest xampp. Can you guys help me solve this
It because you are referencing to a column which does not have a separate key, although it is part of a compound key.
Try adding a KEY in it, eg
CREATE TABLE IF NOT EXISTS `userinit`
(
......
KEY (cmnd), -- <<=== HERE
PRIMARY KEY (`id`,`usn`,`cmnd`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
SQLFiddle Demo

Optimize Join sentence with foreign keys, and show records with nulls

I have the following structure
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
CREATE TABLE IF NOT EXISTS `sis_param_tax` (
`id` int(5) NOT NULL auto_increment,
`description` varchar(50) NOT NULL,
`code` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7;
CREATE TABLE IF NOT EXISTS `sis_param_city` (
`id` int(4) NOT NULL auto_increment,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `sis_supplier` (
`id` int(15) NOT NULL auto_increment,
`name` varchar(200) NOT NULL,
`address` varchar(200) default NULL,
`phone` varchar(30) NOT NULL,
`fk_city` int(11) default NULL,
`fk_tax` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `fk_city` (`fk_city`),
KEY `fk_tax` (`fk_tax`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
ALTER TABLE `sis_supplier`
ADD CONSTRAINT `sis_supplier_ibfk_4` FOREIGN KEY (`fk_tax`) REFERENCES `sis_param_tax` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT `sis_supplier_ibfk_3` FOREIGN KEY (`fk_city`) REFERENCES `sis_param_city` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
My questions are
1. This structure allows me to have a supplier with city and tax fields = null (in case user didn't set these values). Right?
2. If I delete "X" city, supplier's fk_city with city="X" are set to null, same with fk_tax. Right?
3. I want to optimize (IF POSSIBLE) the following join sentence, so I can show suppliers whom have fk_city and/or fk_tax = NULL
SELECT DISTINCT
sis_supplier.id,
sis_supplier.name,
sis_supplier.telefono,
sis_supplier.address,
sis_supplier.phone,
sis_supplier.cuit,
sis_param_city.name AS city,
sis_param_tax.description AS tax,
sis_supplier.fk_city,
sis_supplier.fk_tax
FROM
sis_supplier
LEFT OUTER JOIN sis_param_city
ON
sis_supplier.`fk_city` = sis_param_city.id
LEFT OUTER JOIN `sis_param_tax`
ON
sis_supplier.`fk_tax` = `sis_param_tax`.`id`
Thanks a lot in advance,
Yes.
Yes.
Yes, it's good to optimize. The query you showed looks fine. How is it not working for you?
Have you analyzed the query with EXPLAIN? This can help you tell when you have a query that isn't using indexes effectively. In fact, all of Chapter 7 Optimization would be recommended reading.
if you want to show records with nulls than use RIGHT or LEFT JOIN
depend on your needs