Problem adding Foreign Key using Alter Table with existing MYSQL Database - can't add it! Help!

廉价感情. 提交于 2019-11-28 11:14:27

Are both tables InnoDB type?

Does the company table have an index on company_id ?

I guess that your table is MyISAM (the default if you haven't changed the config) and you can't create foreign key constraints in MyISAM. See the description of the CREATE TABLE for yout two tables.

If both tables are empty, drop them and re-create them, choosing InnoDB as engine. You could also add the FOREIGN KEY constraints in the tables creation script(s).


From MySQL Reference Manual:

Foreign keys definitions are subject to the following conditions:

  • Both tables must be InnoDB tables and they must not be TEMPORARY tables.

  • Corresponding columns in the foreign key and the referenced key must have similar internal data types inside InnoDB so that they can be compared without a type conversion. The size and sign of integer types must be the same. The length of string types need not be the same. For nonbinary (character) string columns, the character set and collation must be the same.

  • InnoDB requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. (This is in contrast to some older versions, in which indexes had to be created explicitly or the creation of foreign key constraints would fail.) index_name, if given, is used as described previously.

  • InnoDB permits a foreign key to reference any index column or group of columns. However, in the referenced table, there must be an index where the referenced columns are listed as the first columns in the same order.

  • Index prefixes on foreign key columns are not supported. One consequence of this is that BLOB and TEXT columns cannot be included in a foreign key because indexes on those columns must always include a prefix length.

  • If the CONSTRAINT symbol clause is given, the symbol value must be unique in the database. If the clause is not given, InnoDB creates the name automatically.


@egervari: What happens if you run this:

CREATE TABLE `test` (
  `company_id` bigint(20) NOT NULL,
  `module_id` bigint(20) NOT NULL,

  KEY  (`module_id`),
  KEY  (`company_id`),

  CONSTRAINT `test_fk_module`
    FOREIGN KEY (`module_id`)
    REFERENCES `module` (`module_id`),

  CONSTRAINT `test_fk_company`
    FOREIGN KEY (`company_id`)
    REFERENCES `company` (`company_id`)
    ON DELETE RESTRICT
    ON UPDATE RESTRICT

) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

And if you run:

ALTER TABLE `company_to_module`
  ADD CONSTRAINT `company_to_module_fk_company` 
    FOREIGN KEY (`company_id`)
    REFERENCES `company` (`company_id`)
    ON DELETE RESTRICT
    ON UPDATE RESTRICT;

Ensure that company_to_module.company_id and company.company_id are the EXACT same datatype. I had this happen when the primary key was setup as an UNSIGNED INT but the foreign key field was just an INT. Adding UNSIGNED to the datatype fixed the problem.

I have simply applied the refactorings using Windows and then reimported the database into Debian - it works.

I think it's safe to say that something was messed up on the Debian server, or with the linux version of Mysql - perhaps a bug in 5.1 build?

Anyway, I have also upgraded the ram on the server from 1gb to 2gb, and these problems have gone away.

I think MySQL maybe just didn't have enough ram to complete the operation. If that was the case (and it seems to be), I think MySQL should have simply said so rather than spitting out these errors - making me and everyone here think it was a syntax or a schema-related problem.

Anyway, thanks for those that tried to help. At least it helped me to isolate all the things it couldn't have been.

Since it doesn't seem to be anything syntax-related, my best guess would be that you're running out of space for creating InnoDB tables.

EDIT: Can you paste your InnoDB configuration:

SHOW VARIABLES LIKE "inno%";

Since trying to create a copy of company_to_module manually gives you the same error, you should carefully check the fk constraint already present in company_to_module. Is it still valid, or did you modify the table module?

From the MySQL-Docs:

1005 (ER_CANT_CREATE_TABLE) Cannot create table. If the error message refers to error 150, table creation failed because a foreign key constraint was not correctly formed.

@egervari You wrote - My solution was to drop all the indexes and foreign keys, rename the id columns, and then re-add the indexes and foreign keys.

Agree with you. But it might be that something went wrong. I reproduced the error, and (in my case) fixed it.

I'd suggest you to run OPTIMIZE TABLE command for table where column was renamed. Documentation says - For InnoDB tables, OPTIMIZE TABLE is mapped to ALTER TABLE, which rebuilds the table to update index statistics and free unused space in the clustered index.


One more solution:

Drop unique key in the referenced table (key that is used by foreign key, in your case it is a primary key). Then add new foreign key and recreate droped unique key.


One more solution:

Try to add and drop new column to the referenced table, then try to create your foreign key.

ALTER TABLE company ADD COLUMN column1 VARCHAR(255) DEFAULT NULL;
ALTER TABLE company DROP COLUMN column1;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!