Can't create mysql table with foreign key - mysql

I am getting errno 150 when I try to create the following two tables.
CREATE TABLE `mydatabase`.`userstatus`(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(50) NOT NULL ,
`description` VARCHAR(255) ,
PRIMARY KEY (`id`)
);
CREATE TABLE `mydatabase`.users(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`email` VARCHAR(200) NOT NULL ,
`username` VARCHAR(20) NOT NULL DEFAULT 'Unknown' ,
`userstatusid` INT UNSIGNED NOT NULL DEFAULT 2 ,
`datemodified` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`datecreated` DATETIME DEFAULT 0 NOT NULL ,
PRIMARY KEY (`id`),
UNIQUE (username),
UNIQUE (email),
INDEX userstatusid_index (userstatusid),
CONSTRAINT fk_users_userstatus FOREIGN KEY (userstatusid) REFERENCES userstatus(id)
ON DELETE SET NULL
ON UPDATE CASCADE
) ENGINE=INNODB ROW_FORMAT=DEFAULT ;
What's causing the error and how do I fix it?

I put on delete set null but the column has been defined as not null. I was focusing too much attention to the types which usually causes the errno 150.

Maybe you could try set a Unique key on userstatusid.
Sometimes that may help.

You can try SHOW INNODB STATUS which will show the last InnoDB error (e.g. foreign key constraint definition problems).
(Otherwise you have to just guess based on the error number and limited information which the error from the statement provides, which isn't ideal.)

Related

The auto_increment value is less than the max ID in table?

I'm using Mysql 5.6.46.
And the final sql execute in my code is
REPLACE ... .
I'm using multi thread way to batch insert data into my db table.
The question is the AUTO_INCREMENT is less than my table max ID, and then I can not write data into this table for it always raise error Duplicate entry '31245418' for key 'PRIMARY'
SELECT AUTO_INCREMENT
FROM information_schema.tables WHERE table_schema='db' AND table_name='table';
# 31245419
SELECT id FROM spend_daily_level ORDER BY id DESC LIMIT 1
# 31247125
How can I avoid this problem? Thanks
I will provide more detail info if it's necessary
Update more info
CREATE TABLE `spend_daily_level` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`active` tinyint(1) NOT NULL ,
`created_time` datetime(6) NOT NULL ,
`updated_time` datetime(6) NOT NULL ,
`date` date NOT NULL ,
`system_value` decimal(16,2) NOT NULL ,
`checked_value` decimal(16,2) NOT NULL ,
`account_id` int(11) NOT NULL ,
`sale_leader_id` int(11) DEFAULT NULL ,
`account_status` tinyint(3) DEFAULT '1' ,
PRIMARY KEY (`id`),
UNIQUE KEY `spend_daily_level_date_account_id_f38b1186_uniq` (`date`,`account_id`),
KEY `spend_daily_level_account_id_f6df4f99_fk_account_id` (`account_id`),
KEY `sale_leader_id` (`sale_leader_id`),
KEY `date_active` (`active`,`date`),
CONSTRAINT `spend_daily_level_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`),
CONSTRAINT `spend_daily_level_ibfk_2` FOREIGN KEY (`sale_leader_id`) REFERENCES `sale_leader` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=31245419 DEFAULT CHARSET=utf8 COMMENT='daily_spend'

Why MySQL does not accept my foreign keys?

I have 26 tables that are very dependent from each other. I crated each table and then executed in the database through MySQL Workbench. Then I build the model where I linked those tables creating the foreign keys. I exported that back in to metadata and I had now the complete code of the tables with the proper foreign data created by the application, so I made not mistakes.
But when I put the file in my server to run by phpMyAdmin, I get a 150 error that does not specify where it is. I Googled it but each case is different and mine is that the FK are not the auto incremented field, but a string field called UT that I created which has the Time Unit when I created a row.
CREATE TABLE IF NOT EXISTS `eduardo8_plataforma`.`aplicativo` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT ,
`ut` VARCHAR(20) NOT NULL ,
`nome` VARCHAR(99) NOT NULL ,
`ver` VARCHAR(20) NULL DEFAULT NULL ,
`descr` VARCHAR(254) NULL DEFAULT NULL ,
`tag` VARCHAR(254) NULL DEFAULT NULL ,
`url` VARCHAR(254) NULL DEFAULT NULL ,
`cad` VARCHAR(20) NULL DEFAULT NULL ,
`obj` TEXT NULL DEFAULT NULL ,
`tab` VARCHAR(254) NULL DEFAULT NULL ,
`dbn` VARCHAR(254) NULL DEFAULT NULL ,
`dbu` VARCHAR(254) NULL DEFAULT NULL ,
`dbs` VARCHAR(254) NULL DEFAULT NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `nome` (`nome` ASC) ,
UNIQUE INDEX `ut_UNIQUE` (`ut` ASC) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_swedish_ci;
CREATE TABLE IF NOT EXISTS `eduardo8_plataforma`.`modulo` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT ,
`ut` VARCHAR(20) NOT NULL ,
`app` VARCHAR(20) NULL DEFAULT NULL ,
`lic` VARCHAR(20) NULL DEFAULT NULL ,
`tipo` VARCHAR(20) NULL DEFAULT NULL ,
`nome` VARCHAR(99) NOT NULL ,
`classe` VARCHAR(99) NOT NULL ,
`obj` TEXT NULL DEFAULT NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `ut_UNIQUE` (`ut` ASC) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_swedish_ci;
CREATE TABLE IF NOT EXISTS `eduardo8_plataforma`.`modulo_app` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT ,
`ut` VARCHAR(20) NOT NULL ,
`app` VARCHAR(20) NOT NULL ,
`modulo` VARCHAR(20) NOT NULL ,
PRIMARY KEY (`id`) ,
INDEX `fk_modulo_app_modulo1` (`modulo` ASC) ,
INDEX `fk_modulo_app_aplicativo1` (`app` ASC) ,
UNIQUE INDEX `ut_UNIQUE` (`ut` ASC) ,
CONSTRAINT `fk_modulo_app_modulo1`
FOREIGN KEY (`modulo` )
REFERENCES `eduardo8_plataforma`.`modulo` (`ut` )
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT `fk_modulo_app_aplicativo1`
FOREIGN KEY (`app` )
REFERENCES `eduardo8_plataforma`.`aplicativo` (`ut` )
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_swedish_ci;
The table that worked (after answers):
CREATE TABLE IF NOT EXISTS `eduardo8_plataforma`.`modulo_app` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT ,
`ut` VARCHAR(20) CHARACTER SET 'utf8' COLLATE 'utf8_swedish_ci' UNIQUE NOT NULL ,
`app` VARCHAR(20) CHARACTER SET 'utf8' COLLATE 'utf8_swedish_ci' NOT NULL ,
`modulo` VARCHAR(20) CHARACTER SET 'utf8' COLLATE 'utf8_swedish_ci' NOT NULL ,
PRIMARY KEY (`id`) ,
INDEX `fk_modulo_app_modulo1` (`modulo` ASC) ,
INDEX `fk_modulo_app_aplicativo1` (`app` ASC) ,
UNIQUE INDEX `ut_UNIQUE` (`ut` ASC) ,
CONSTRAINT `fk_modulo_app_modulo1`
FOREIGN KEY (`modulo` )
REFERENCES `eduardo8_plataforma`.`modulo` (`ut` )
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT `fk_modulo_app_aplicativo1`
FOREIGN KEY (`app` )
REFERENCES `eduardo8_plataforma`.`aplicativo` (`ut` )
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_swedish_ci;
You need to move the CREATE INDEX clauses before the foreign keys, as foreign key cannot reference non-indexed field.
The short story is that a foreign key should reference a candidate key column. That is, it should reference a column that is declared either
primary key, or
not null unique.
A standard SQL dbms will raise an error if you reference a column that isn't unique. MySQL should, too, but it won't.
Mysql Docs say
. . . the system does not enforce a requirement that the referenced columns
be UNIQUE or be declared NOT NULL. The handling of foreign key
references to nonunique keys or keys that contain NULL values is not
well defined for operations such as UPDATE or DELETE CASCADE. You are
advised to use foreign keys that reference only UNIQUE (including
PRIMARY) and NOT NULL keys.
If you need non-unique data from another table, join it in a query, or join it in a view.

mysql won't allow foreign key

Many people had this problem already, but there was no fitting solution in other posts.
I have two tables, one named "sales", the other named "host_flags". I would like to have a foreign key for host_flags.sales_id to sales.id, but mysql won't let me! I have primary indexes defined in each table, so I wonder why...
The host_flags table already has a foreign key on the column host_id, but even when I tried and created the foreign key for the sales id first, it wouldn't let me.
The tables look like:
CREATE TABLE `sales` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`creation` datetime DEFAULT NULL,
`lastupdate` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
CREATE TABLE `host_flags` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`host_id` int(11) DEFAULT NULL,
`sales_id` int(11) DEFAULT NULL,
`creation` datetime DEFAULT NULL,
`lastupdate` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `host_id6` (`host_id`),
CONSTRAINT `host_id6` FOREIGN KEY (`host_id`) REFERENCES `hosts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `hosts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`creation` datetime NOT NULL,
`lastupdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32225 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
I get this error message:
MySQL said: Can't create table 'primarydata.#sql-191_1' (errno: 150)
Thanks!
Charles
SOLUTION FOUND
All ints of the primary indexes have to be either signed or unsigned - not mixed.
Typically:
I like to declare the FK constraints outside of the table definition after all tables have been constructed.
ALTER TABLE `tbl`
ADD CONSTRAINT `constr`
FOREIGN KEY `fk_id` REFERENCES `ftbl`(`id`)
ON UPDATE CASCADE
ON DELETE CASCADE;
This way I can make sure the problem isn't something like the datatype of tbl.fk_id not being the same as the one of ftbl.id (including UNSIGNED as #Devart said). Or not having declared ftbl.id as unique. Regardless of the order of declaration of the tables.
After i do this i can integrate the constraint back into the table definition and take into account the order in which the tables need to be created to allow the constraint to be added.
You problem:
-- creating the sales table
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-- creating the host_flags table
`sales_id` int(11) DEFAULT NULL,
-- the sales.id is declared as unsigned
-- the host_flags.sales_id is declared signed
Additonally to Recursed's answer:
There is a requirement that foreign keys contstraints' names must be unique in database scope. Maybe changing the name will work?
There is also a huge thread on MySQL community forums about the problem containing several solutions for some specific situations.
Possible two errors:
Reference and referenced columns must have the same type - int(11) unsigned
Unknown referenced table hosts.

Foreign key constraint is incorrectly formed?

I got this error when create table: Foreign key constraint is incorrectly formed?
create table comment(
Comment_ID int UNSIGNED AUTO_INCREMENT not null,
User_1 varchar(50) not null,
Note_ID int(11) UNSIGNED not null,
PRIMARY key(Comment_ID),
CONSTRAINT `fk_1` FOREIGN KEY (`User_1`) REFERENCES `user` (`Dev_ID`),
CONSTRAINT `fk_2` FOREIGN KEY (`User_2`) REFERENCES `user` (`Dev_ID`),
CONSTRAINT `fk_3` FOREIGN KEY (`Note_ID`) REFERENCES `note`(`Note_ID`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
it's OK when I remove fk_3.
This my note table
CREATE TABLE `note` (
`Dev_ID` varchar(50) NOT NULL,
`Note_ID` int(11) UNSIGNED NOT NULL,
`Title` varchar(200) NOT NULL,
`Time` datetime NOT NULL,
`Mood` int(11) NOT NULL,
`Body` varchar(3000) NOT NULL,
`Visible` tinyint(1) NOT NULL DEFAULT '1',
`Share` tinyint(1) NOT NULL DEFAULT '0',
`Update` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`Dev_ID`,`Note_ID`),
CONSTRAINT `fk_note_user` FOREIGN KEY (`Dev_ID`)
REFERENCES `user` (`Dev_ID`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Thanks for help!
That's because the primary key of the note table is (Dev_ID,Note_ID) but you are only referencing one of those columns (Note_ID) in your constraint.
A FK constraint must always consist of all PK columns.
Also make sure that both tables are innoDB.
In addition to the answers that have been given, you would also get this error if the field types did not match. For example, if you tried to create a foreign key constraint between a varchar field and an int field.
This problem occur because the column
`Note_ID` int(11) UNSIGNED NOT NULL
Is neither primary nor unique.
Just make it
`Note_ID` int(11) UNSIGNED NOT NULL UNIQUE
And it will work.
One more addition: charsets of the fields must match.
In the referenced table I had ascii as a default charset: DEFAULT CHARSET=ascii was reported by show create table. I tried to create the referencing table with DEFAULT CHARSET=utf and I got 'Foreign key constraint is incorrectly formed'.
After I changed this to DEFAULT CHARSET=ascii on the new table (the referencing one), it was created successfully.
Ensure the collation is the same on both fields. I had the same problem when one was latin-general-ci and the other was utf8_unicode_ci. Not sure why the collation changed on the one table but fixing this resolved the issue.

MySQL: Error Message Can't create table (errno: 150)

I have two tables, 'po' and 'receive'
CREATE TABLE `po` (
`PO_ID` bigint(20) NOT NULL,
`SERVICE_TYPE` bit(1) DEFAULT NULL,
`ENTRY_DATE` date NOT NULL,
`RECEIPT_DATE` date DEFAULT NULL,
`TURNOVER` date DEFAULT NULL,
`MOBILIZATION` date DEFAULT NULL,
`SITE_NAME` varchar(255) NOT NULL,
`SITE_CODE` varchar(45) DEFAULT NULL,
`SITE_TIN` varchar(45) DEFAULT NULL,
`SITE_ADDRESS` varchar(255) NOT NULL,
`COST` decimal(11,2) NOT NULL,
`XML` text,
PRIMARY KEY (`PO_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
CREATE TABLE `receive` (
`RECEIPT_ID` varchar(100) NOT NULL,
`RECEIPT_DATE` date NOT NULL,
`PO_NUMBER` bigint(20) NOT NULL,
`SUPPLIER_ID` int(11) NOT NULL,
PRIMARY KEY (`RECEIPT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
I'm trying to connect two tables by defining a foreign key 'fk_po' on the table 'receive'
ALTER TABLE `fourthwave`.`receive`
ADD CONSTRAINT `fk_po`
FOREIGN KEY (`PO_NUMBER` )
REFERENCES `fourthwave`.`po` (`PO_ID` )
ON DELETE SET NULL
ON UPDATE SET NULL
, ADD INDEX `fk_po` (`PO_NUMBER` ASC)
However, the alter query above throws an error :
Error Code: 1005. Can't create table 'fourthwave.#sql-aec_11' (errno:150)
Am i getting this error because the field's names, 'PO_ID' and 'PO_NUMBER' on both tables are different?
Execute SHOW ENGINE INNODB STATUS statement after ALTER TABLE, and you will see the error message - 'You have defined a SET NULL condition though some of the
columns are defined as NOT NULL'.
ALTER TABLE `receive`
ADD CONSTRAINT `fk_po`
FOREIGN KEY (`PO_NUMBER` )
REFERENCES `po` (`PO_ID` )
ON DELETE SET NULL
ON UPDATE SET NULL
, ADD INDEX `fk_po` (`PO_NUMBER` ASC);
SHOW ENGINE INNODB STATUS;
You need an index on PO_NUMBER in the receive table. The field you are referencing in a foreign key always should be indexed.