mysql innodb altering two tables that have foreign keys - mysql

Below is my current database structure
CREATE TABLE one (
id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id));
CREATE TABLE two (
id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
one_id MEDIUMINT UNSIGNED NOT NULL
PRIMARY KEY (id),
CONSTRAINT FOREIGN KEY (`one_Id`) REFERENCES `one` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
How can I run the following alter command on both tables
ALTER TABLE one MODIFY COLUMN `id` int(10) NOT NULL auto_increment;
ALTER TABLE two MODIFY COLUMN `one_id` int(10) NOT NULL;
Right now I'm getting this error
ERROR 1025 (HY000): Error on rename (errno: 150)
I've also tried to disable these but it doesn't help
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;

Assuming your constraint name in table two is two_ibfk_1 , you can see the name of the constraint with this command :
SHOW CREATE TABLE two;
so the command would be to delete the constraint first, and then recreate it after it was modified
ALTER TABLE two DROP FOREIGN KEY two_ibfk_1;
ALTER TABLE one MODIFY COLUMN `id` int(10) NOT NULL auto_increment;
ALTER TABLE two MODIFY COLUMN `one_id` int(10) NOT NULL ;
ALTER TABLE two ADD CONSTRAINT FOREIGN KEY (`one_Id`) REFERENCES `one` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
FYI, the second command to modify table two can not be set as auto_increment, because the primary is is column id

This is straight from the a ALTER TABLE documentation for MySQL:
Before MySQL 5.6.7, using ALTER TABLE to change the definition of a
foreign key column could cause a loss of referential integrity. For
example, changing a foreign key column that contained NULL values to
be NOT NULL caused the NULL values to be the empty string. Similarly,
an ALTER TABLE IGNORE that removed rows in a parent table could break
referential integrity.
As of 5.6.7, the server prohibits changes to foreign key columns with
the potential to cause loss of referential integrity. A workaround is
to use ALTER TABLE ... DROP FOREIGN KEY before changing the column
definition and ALTER TABLE ... ADD FOREIGN KEY afterward.
This makes the other answer correct. The SET foreign_key_checks=0; statement and its brethren will disable constraints, but will not let you modify a table such that an existing constraint can no longer even exist.

Related

Drop foreign key MySQL does not exist

I have a table in MySQL like this (this is returned from using show create table user_org_contacts):
CREATE TABLE `user_org_contacts` (
`user_org_contacts_id` int(11) NOT NULL AUTO_INCREMENT,
`from_user_id` int(11) DEFAULT NULL,
`to_org_user_id` int(11) DEFAULT NULL,
`suggested_vacancy_id` int(11) DEFAULT NULL,
`contact_date` datetime NOT NULL,
`message` text,
PRIMARY KEY (`user_org_contacts_id`),
KEY `FK_Reference_53` (`from_user_id`),
KEY `FK_Reference_54` (`to_org_user_id`),
KEY `FK_Reference_55` (`suggested_vacancy_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=latin1
I have noticed that my FK_Reference_54 is wrong and points to the wrong table. So I would like to change this one by the correct FK.
This is what I tried:
ALTER TABLE `user_org_contacts`
DROP FOREIGN KEY `FK_Reference_54`;
ALTER TABLE `user_org_contacts`
ADD CONSTRAINT `FK_Reference_54`
FOREIGN KEY (`to_org_user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE;
This produces the following error:
1091 - Can't DROP 'FK_Reference_54'; check that column/key exists
The problem is that you are confusing indexes with primary keys.
The keyword KEY is actually showing you indexes while primary keys use the keywords CONSTRAINT ... FOREIGN KEY ...
Example:
CONSTRAINT `FK_name` FOREIGN KEY (`current_field_name`)
REFERENCES `external_table_name` (`external_field_name`) ON DELETE CASCADE ON UPDATE CASCADE
So in your case, if you want to remove your INDEX you just need to call this query
ALTER TABLE `user_org_contacts`
DROP INDEX `FK_Reference_54`;
Next time I suggest you using some UI for mysql like mysql workbench, with that you would have noticed the issue immediatly.
First Try To remove that column
ALTER TABLE tablename DROP COLUMN columname;
Then:
ALTER TABLE tablename ADD columnname datatype.
Or you can try this Modify option like.
ALTER TABLE tablename MODIFY COLUMN columnname datatype;
Hope This will help you.

Cannot truncate a table referenced in a foreign key constraint from empty table

I have the following tables:
CREATE TABLE `companies_investorfundinground` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`funding_round_id` int(11) NOT NULL,
`investor_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `companies_funding_round_id_8edc4cc4_fk_companies_fundinground_id` (`funding_round_id`),
KEY `companies_investor_investor_id_30d4fd3e_fk_companies_investor_id` (`investor_id`),
CONSTRAINT `companies_funding_round_id_8edc4cc4_fk_companies_fundinground_id` FOREIGN KEY (`funding_round_id`) REFERENCES `companies_fundinground` (`id`),
CONSTRAINT `companies_investor_investor_id_30d4fd3e_fk_companies_investor_id` FOREIGN KEY (`investor_id`) REFERENCES `companies_investor` (`id`)
)
CREATE TABLE `companies_fundinground` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`funding_round_code` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `companies_fundinground_447d3092` (`company_id`),
CONSTRAINT `companies_company_id_36dd5970_fk_companies_company_entity_ptr_id` FOREIGN KEY (`company_id`) REFERENCES `companies_company` (`entity_ptr_id`)
)
I was able to truncate companies_investorfundinground.
I try to delete companies_fundinground but I get the error:
Cannot truncate a table referenced in a foreign key constraint companies_funding_round_id_8edc4cc4_fk_companies_fundinground_id
Why am I getting this error if companies_investorfundinground is completely truncated?
TRUNCATE TABLE is equivalent to dropping the table and recreating it as a new table. This would break the foreign key reference.
It says in https://dev.mysql.com/doc/refman/5.7/en/truncate-table.html:
Logically, TRUNCATE TABLE is similar to a DELETE statement that deletes all rows, or a sequence of DROP TABLE and CREATE TABLE statements. To achieve high performance, it bypasses the DML method of deleting data. Thus, it cannot be rolled back, it does not cause ON DELETE triggers to fire, and it cannot be performed for InnoDB tables with parent-child foreign key relationships.
Consider this another way: if TRUNCATE TABLE is supposed to be fast and efficient, is it worth spending the time to check a child table to see if it has any referencing rows? That table might have millions of rows, but have NULL in its foreign key column on all rows.
If you know for certain that you won't upset the child table, you have a workaround:
mysql> create table p ( id int primary key );
mysql> create table f ( pid int, foreign key (pid) references p(id));
mysql> truncate table p;
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint
(`test`.`f`, CONSTRAINT `f_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `test`.`p` (`id`))
mysql> set foreign_key_checks=0;
mysql> truncate table p;
mysql> set foreign_key_checks=1;

mySQL How to alter column to have foreign key?

I want to alter a column in one of my tables to that it references another column in another table. I've tried to introduce a foreign key the following ways:
ALTER TABLE `table` ALTER COLUMN `id_l` int NOT NULL, foreign key (`id_l`) references table_b(`id_l`);
ALTER TABLE `table` CHANGE `id_l` `id_l` int NOT NULL, foreign key (`id_l`) references table_b(`id_l`);
I am thrown a syntax error.
A work around is to delete the table and create a new one with the desired reference (this works) but I want to change this table as it is, not to transfer the data. How do I do this?
MySQL Server 5.6.17
Just use ALTER TABLE along with ADD CONSTRAINT:
ALTER TABLE `table` ADD CONSTRAINT fk_l_id FOREIGN KEY (id_l) REFERENCES table_b(id_l);
if you already have a foreign key and you want to change it you can do :
ALTER TABLE your_table DROP CONSTRAINT your_constraint;
then:
ALTER TABLE your_table ADD FOREIGN KEY (your_column) REFERENCES other_table(other_column);
if you don't know your constraint name you can do SHOW CREATE TABLE mytable;
I had problem with other answers. and after some research I find this answer
ALTER TABLE `TABLE_NAME`
ADD COLUMN `COLUMN_NAME` BIGINT(20) UNSIGNED NULL DEFAULT NULL AFTER
`AFTER_COLUMN_NAME`,
ADD FOREIGN KEY `FOREIGN_RELATION_NAME`(`COLUMN_NAME`) REFERENCES
`FOREIGN_TABLE`(`FOREIGN_COLUMN`) ON UPDATE SET NULL ON DELETE SET NULL

Add Foreign Key to existing table

I want to add a Foreign Key to a table called "katalog".
ALTER TABLE katalog
ADD CONSTRAINT `fk_katalog_sprache`
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;
When I try to do this, I get this error message:
Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150)
Error in INNODB Status:
120405 14:02:57 Error in foreign key constraint of table
mytable.#sql-7fb1_7d3a:
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL:
Cannot resolve table name close to:
(`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL
When i use this query it works, but with wrong "on delete" action:
ALTER TABLE `katalog`
ADD FOREIGN KEY (`Sprache` ) REFERENCES `sprache` (`ID` )
Both tables are InnoDB and both fields are "INT(11) not null". I'm using MySQL 5.1.61. Trying to fire this ALTER Query with MySQL Workbench (newest) on a MacBook Pro.
Table Create Statements:
CREATE TABLE `katalog` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`AnzahlSeiten` int(4) unsigned NOT NULL,
`Sprache` int(11) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `katalogname_uq` (`Name`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC$$
CREATE TABLE `sprache` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Bezeichnung` varchar(45) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `Bezeichnung_UNIQUE` (`Bezeichnung`),
KEY `ix_sprache_id` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
To add a foreign key (grade_id) to an existing table (users), follow the following steps:
ALTER TABLE users ADD grade_id SMALLINT UNSIGNED NOT NULL DEFAULT 0;
ALTER TABLE users ADD CONSTRAINT fk_grade_id FOREIGN KEY (grade_id) REFERENCES grades(id);
Simply use this query, I have tried it as per my scenario and it works well
ALTER TABLE katalog ADD FOREIGN KEY (`Sprache`) REFERENCES Sprache(`ID`);
Simple Steps...
ALTER TABLE t_name1 ADD FOREIGN KEY (column_name) REFERENCES t_name2(column_name)
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;
But your table has:
CREATE TABLE `katalog` (
`Sprache` int(11) NOT NULL,
It cant set the column Sprache to NULL because it is defined as NOT NULL.
check this link. It has helped me with errno 150:
http://verysimple.com/2006/10/22/mysql-error-number-1005-cant-create-table-mydbsql-328_45frm-errno-150/
On the top of my head two things come to mind.
Is your foreign key index a unique name in the whole database (#3 in the list)?
Are you trying to set the table PK to NULL on update (#5 in the list)?
I'm guessing the problem is with the set NULL on update (if my brains aren't on backwards today as they so often are...).
Edit: I missed the comments on your original post. Unsigned/not unsigned int columns maybe resolved your case. Hope my link helps someone in the future thought.
How to fix Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150) in mysql.
alter your table and add an index to it..
ALTER TABLE users ADD INDEX index_name (index_column)
Now add the constraint
ALTER TABLE foreign_key_table
ADD CONSTRAINT foreign_key_name FOREIGN KEY (foreign_key_column)
REFERENCES primary_key_table (primary_key_column) ON DELETE NO ACTION
ON UPDATE CASCADE;
Note if you don't add an index it wont work.
After battling with it for about 6 hours I came up with the solution
I hope this save a soul.
MySQL will execute this query:
ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
Cheers!
When you add a foreign key constraint to a table using ALTER TABLE, remember to create the required indexes first.
Create index
Alter table
try all in one query
ALTER TABLE users ADD grade_id SMALLINT UNSIGNED NOT NULL DEFAULT 0,
ADD CONSTRAINT fk_grade_id FOREIGN KEY (grade_id) REFERENCES grades(id);
step 1: run this script
SET FOREIGN_KEY_CHECKS=0;
step 2: add column
ALTER TABLE mileage_unit ADD COLUMN COMPANY_ID BIGINT(20) NOT NULL
step 3: add foreign key to the added column
ALTER TABLE mileage_unit
ADD FOREIGN KEY (COMPANY_ID) REFERENCES company_mst(COMPANY_ID);
step 4: run this script
SET FOREIGN_KEY_CHECKS=1;
ALTER TABLE child_table_name ADD FOREIGN KEY (child_table_column) REFERENCES parent_table_name(parent_table_column);
child_table_name is that table in which we want to add constraint.
child_table_column is that table column in which we want to add foreign key.
parent table is that table from which we want to take reference.
parent_table_column is column name of the parent table from which we take reference
this is basically happens because your tables are in two different charsets. as a example one table created in charset=utf-8 and other tables is created in CHARSET=latin1 so you want be able add foriegn key to these tables. use same charset in both tables then you will be able to add foriegn keys. error 1005 foriegn key constraint incorrectly formed can resolve from this
The foreign key constraint must be the same data type as the primary key in the reference table and column
ALTER TABLE TABLENAME ADD FOREIGN KEY (Column Name) REFERENCES TableName(column name)
Example:-
ALTER TABLE Department ADD FOREIGN KEY (EmployeeId) REFERENCES Employee(EmployeeId)
i geted through the same problem. I my case the table already have data and there were key in this table that was not present in the reference table. So i had to delete this rows that disrespect the constraints and everything worked.
Double check if the engine and charset of the both tables are the same.
If not, it will show this error.

mysql alter int column to bigint with foreign keys

I want to change the datatype of some primary-key columns in my database from INT to BIGINT. The following definition is a toy-example to illustrate the problem:
CREATE TABLE IF NOT EXISTS `owner` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `thing_id` (`thing_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
DROP TABLE IF EXISTS `thing`;
CREATE TABLE IF NOT EXISTS `thing` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
ALTER TABLE `owner`
ADD CONSTRAINT `owner_ibfk_1` FOREIGN KEY (`thing_id`) REFERENCES `thing` (`id`);
Now when i try to execut one of the following commands:
ALTER TABLE `thing` CHANGE `id` `id` BIGINT NOT NULL AUTO_INCREMENT;
ALTER TABLE `owner` CHANGE `thing_id` `thing_id` BIGINT NOT NULL;
i'm running into an error
#1025 - Error on rename of './debug/#[temp-name]' to './debug/[tablename]' (errno: 150)
SHOW INODB STATUS outputs:
LATEST FOREIGN KEY ERROR
------------------------
120126 13:34:03 Error in foreign key constraint of table debug/owner:
there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:
,
CONSTRAINT "owner_ibfk_1" FOREIGN KEY ("thing_id") REFERENCES "thing" ("id")
I'm guessing that the foreign key definition blocks changing the column type on either side. The naive approach to solve this problem would be to delete the foreign key definitions, alter the columns and re-define the foreign keys. is there a better solution?
Even with SET foreign_key_checks = 0, you can't alter the type of the constraint column.
From MySQL doc : http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
However, even if foreign_key_checks = 0, InnoDB does not permit the creation of a foreign key constraint where a column references a nonmatching column type.
So, I agree with the comment of Devart. Just drop it and create it again.
I could suggest you to rename such fields in GUI tool - dbForge Studio for MySQL (free trial edition):
Just select the field you want to rename in the Database Explorer, click on Refactoring->Rename command, enter new name in openned window, and press OK, it will rename the field and recreate all foreign keys automatically.
Even though you changed the column size of id and thing_id, the raw data in the rows is still 4 byte integers instead of 8 byte integers. But you can convert the data.
Try this solution instead. I had to do something similar recently on a large data set, converting INT columns to BIGINT when the data set threatened to grow too large.
ALTER TABLE `owner`
DROP FOREIGN KEY `owner_ibfk_1`;
ALTER TABLE `thing` CHANGE `id` `id` BIGINT NOT NULL AUTO_INCREMENT;
ALTER TABLE `owner` CHANGE `thing_id` `thing_id` BIGINT NOT NULL;
UPDATE `thing` SET `id` = CAST(`id` AS UNSIGNED INTEGER);
UPDATE `owner` SET `thing_id` = CAST(`thing_id` AS UNSIGNED INTEGER);
-- Now the data are BIGINTs; re-create the foreign key constraint
ALTER TABLE `owner`
ADD CONSTRAINT `owner_ibfk_1` FOREIGN KEY (`thing_id`) REFERENCES `thing` (`id`);
I had a similar problem the solution is the change clause:
ALTER TABLE table_name CHANGE id id BIGINT(20) NOT NULL AUTO_INCREMENT;
That worked for me.