9

我有一個生產數據庫,我已經重命名了幾個外鍵的列。很明顯,mysql使我感到非常痛苦。在現有MYSQL數據庫中使用Alter Table添加外鍵問題 - 無法添加!幫幫我!

我的解決方案是刪除所有索引和外鍵,重命名id列,然後重新添加索引和外鍵。

這對於開發數據庫的windows上的mysql 5.1很適用。

我去我的Debian服務器,這也是使用的MySQL 5.1上運行我的遷移腳本,它提供了以下錯誤:

mysql> ALTER TABLE `company_to_module` 
    -> ADD CONSTRAINT `FK82977604FE40A062` FOREIGN KEY (`company_id`) REFERENCES `company` (`company_id`) ON DELETE RESTRICT ON UPDATE RESTRICT; 
ERROR 1005 (HY000): Can't create table 'jobprep_production.#sql-44a5_76' (errno: 150) 

有此表格中沒有值,將與外國發生衝突鍵我正在嘗試添加。數據庫沒有改變。外鍵DID存在於...之前,所以數據沒有問題。我們不要提及我使用了服務器上的SAME數據庫,並且它在Windows上遷移得很好。但是這些相同的外鍵遷移並不在Debian上。

的列使用相同類型 - BIGINT(20)

名稱實際上確實存在各自的表所示。

這些表是innodb。它們在其他列中已經有了外鍵。這不是一個新的數據庫。

我不能刪除表格,因爲這是一個生產數據庫。

「原樣」 在我的數據庫中的表:

CREATE TABLE `company_to_module` (
    `company_id` bigint(20) NOT NULL, 
    `module_id` bigint(20) NOT NULL, 
    KEY `FK8297760442C8F876` (`module_id`), 
    KEY `FK82977604FE40A062` (`company_id`) USING BTREE, 
    CONSTRAINT `FK8297760442C8F876` FOREIGN KEY (`module_id`) REFERENCES `module` (`module_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

而且

Create Table: CREATE TABLE `company` (
    `company_id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) DEFAULT NULL, 
    `address` varchar(255) DEFAULT NULL, 
    `postal_code` varchar(255) DEFAULT NULL, 
    `province_id` bigint(20) DEFAULT NULL, 
    `phone_number` varchar(255) DEFAULT NULL, 
    `is_enabled` bit(1) DEFAULT NULL, 
    `director_id` bigint(20) DEFAULT NULL, 
    `homepage_viewable` bit(1) NOT NULL DEFAULT b'1', 
    `courses_created` int(10) NOT NULL DEFAULT '0', 
    `header_background` varchar(25) DEFAULT '#172636', 
    `display_name` varchar(25) DEFAULT '#ffffff', 
    `tab_background` varchar(25) DEFAULT '#284767', 
    `tab_text` varchar(25) DEFAULT '#ffffff', 
    `hover_tab_background` varchar(25) DEFAULT '#284767', 
    `hover_tab_text` varchar(25) DEFAULT '#f2e0bd', 
    `selected_tab_background` varchar(25) DEFAULT '#f5f5f5', 
    `selected_tab_text` varchar(25) DEFAULT '#172636', 
    `hover_table_row_background` varchar(25) DEFAULT '#c0d2e4', 
    `link` varchar(25) DEFAULT '#4e6c92', 
    PRIMARY KEY (`company_id`), 
    KEY `FK61AE555A71DF3E03` (`province_id`), 
    KEY `FK61AE555AAC50C977` (`director_id`), 
    CONSTRAINT `company_ibfk_1` FOREIGN KEY (`director_id`) REFERENCES `user_account` (`user_account_id`), 
    CONSTRAINT `FK61AE555A71DF3E03` FOREIGN KEY (`province_id`) REFERENCES `province` (`province_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 

這裏是InnoDB的狀態:

------------------------ 
LATEST FOREIGN KEY ERROR 
------------------------ 
110415 3:14:34 Error in foreign key constraint of table jobprep_production/#sql-44a5_1bc: 
FOREIGN KEY (`company_id`) REFERENCES `company` (`company_id`) ON DELETE RESTRICT ON UPDATE RESTRICT: 
Cannot resolve column name close to: 
) ON DELETE RESTRICT ON UPDATE RESTRICT 

如果我嘗試拖放從指數'company_to_module',我得到這個錯誤:

#1025 - Error on rename of './jobprep_production/#sql-44a5_23a' to './jobprep_production/company_to_module' (errno: 150) 

這裏是我的InnoDB的變量:

+---------------------------------+------------------------+ 
| Variable_name     | Value     | 
+---------------------------------+------------------------+ 
| innodb_adaptive_hash_index  | ON      | 
| innodb_additional_mem_pool_size | 1048576    | 
| innodb_autoextend_increment  | 8      | 
| innodb_autoinc_lock_mode  | 1      | 
| innodb_buffer_pool_size   | 8388608    | 
| innodb_checksums    | ON      | 
| innodb_commit_concurrency  | 0      | 
| innodb_concurrency_tickets  | 500     | 
| innodb_data_file_path   | ibdata1:10M:autoextend | 
| innodb_data_home_dir   |      | 
| innodb_doublewrite    | ON      | 
| innodb_fast_shutdown   | 1      | 
| innodb_file_io_threads   | 4      | 
| innodb_file_per_table   | OFF     | 
| innodb_flush_log_at_trx_commit | 1      | 
| innodb_flush_method    |      | 
| innodb_force_recovery   | 0      | 
| innodb_lock_wait_timeout  | 50      | 
| innodb_locks_unsafe_for_binlog | OFF     | 
| innodb_log_buffer_size   | 1048576    | 
| innodb_log_file_size   | 5242880    | 
| innodb_log_files_in_group  | 2      | 
| innodb_log_group_home_dir  | ./      | 
| innodb_max_dirty_pages_pct  | 90      | 
| innodb_max_purge_lag   | 0      | 
| innodb_mirrored_log_groups  | 1      | 
| innodb_open_files    | 300     | 
| innodb_rollback_on_timeout  | OFF     | 
| innodb_stats_on_metadata  | ON      | 
| innodb_support_xa    | ON      | 
| innodb_sync_spin_loops   | 20      | 
| innodb_table_locks    | ON      | 
| innodb_thread_concurrency  | 8      | 
| innodb_thread_sleep_delay  | 10000     | 
+---------------------------------+------------------------+ 

我也想補充一點,當我與添加外鍵播放,MySQL的損壞,我的數據庫,並摧毀了它。我不得不從備份重新加載以再次嘗試。

幫助? :/

+0

這兩個表都是'InnoDB'類型嗎? – 2011-04-15 04:49:53

+0

'company'表是否有'company_id'上的索引? – 2011-04-15 04:50:23

+0

我想你的表是'MyISAM'(默認如果你沒有chnaged配置),我想你不能在MyISAM中創建外鍵約束。請參閱「CREATE TABLE company_to_module」的描述。 – 2011-04-15 04:52:09

回答

1

我只是應用於使用Windows的重構和重新進口,然後在數據庫引入Debian - 它的工作原理。

我認爲這是肯定地說,什麼東西Debian的服務器上搞砸了,或與MySQL的Linux版本 - 或許在5.1構建中的錯誤?

反正我也升級從1GB到2GB服務器上的RAM,而這些問題已經消失。

我認爲MySQL的也許只是沒有足夠的內存來完成操作。如果是這種情況(似乎是這樣),我認爲MySQL應該簡單地說出這樣的話,而不是吐出這些錯誤 - 使我和這裏的每個人都認爲這是一種語法或與模式相關的問題。

無論如何,感謝那些試圖幫助。至少它幫助我隔離了所有不可能的事情。

4

確保company_to_module.company_id和company.company_id是完全相同的數據類型。當主鍵被設置爲UNSIGNED INT但外鍵字段只是一個INT時,我發生了這種情況。將UNSIGNED添加到數據類型解決了問題。

+0

這值得一試。我的所有ID都是BIGINT(20):( – egervari 2011-04-15 05:28:50

+0

我只是想粘貼我的表格定義 – egervari 2011-04-15 05:56:13

+1

爲我工作 - 我有一個unsigned int和另一個int,我試圖鏈接,謝謝你 – 2012-03-15 10:24:39

9

這兩個表的InnoDB類型?

公司表是否在company_id上有索引?

我猜你的表是MyISAM(默認如果你沒有改變配置),你不能在MyISAM中創建外鍵約束。有關兩個表的信息,請參閱CREATE TABLE的說明。

如果兩個表都是空的,請刪除它們並重新創建它們,選擇InnoDB作爲引擎。您還可以在表創建腳本中添加FOREIGN KEY約束。


從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:會發生什麼,如果你運行:

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 ; 

如果你運行:

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; 
+0

是的,我是所有這些事情都做了,表格是Innodb,ID的命名是正確的,數據是正確的,類型是正確的問題:假設我違反了這些規則......爲什麼這些遷移在Windows上使用完全相同的數據庫?這是最令人困惑的事情。 – egervari 2011-04-15 05:31:16

+0

可能內存不足是導致此錯誤的原因嗎?這只是一個雲服務器,「免費」通常說我有29-9 megs沒有1演出。只是好奇:/雖然很多用於緩衝區,所以我不確定這是什麼意思。 – egervari 2011-04-15 07:31:25

+0

@egervari:當你運行上面的CREATE TABLE時,你會得到類似的消息嗎? – 2011-04-15 20:37:47

0

由於它似乎沒有任何與語法相關的東西,我最好的猜測是你的空間不足以創建InnoDB表。

編輯:您可以粘貼您的InnoDB的配置:

SHOW VARIABLES LIKE "inno%"; 
+0

由於某些原因,「innodb_data_file_path」實際上不在my.cnf中。 「innodb_file_per_table」也不是。我個人沒有對my.cnf做過任何事情 - 這是默認設置。這可能是問題嗎?默認值是否真的很低? – egervari 2011-04-15 08:49:19

+0

這是ibdata1的統計信息:「35651584 Apr 15 03:20 ibdata1」 – egervari 2011-04-15 08:55:14

+0

我粘貼了上面的變量;) – egervari 2011-04-15 08:59:41

0

由於試圖創建的company_to_module副本手動給你同樣的錯誤,你應該仔細檢查FK約束已經存在於company_to_module。它還是有效的,還是你修改表module

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.

+0

它給出了錯誤,因爲我忘記更改company_to_module的重複表定義中的外鍵名稱。一旦我意識到這一點,創建表格工作 - 這意味着創建新表格不是問題。但是,刪除'module_id'的索引導致了我上面寫的新錯誤。老實說,我對這種「猜測工作」感到厭倦,我剛剛導出了我的數據庫,在Windows上添加了外鍵(是的,他們工作!),並重新將數據庫導入到debian中。有用。我不知道爲什麼它可以在windows而不是linux上運行。非常適合交叉兼容性。 – egervari 2011-04-15 11:43:31

0

@egervari你寫 - 我的解決辦法是刪除所有索引和外鍵,重命名ID列,然後重新添加索引和外鍵。

同意你的意見。但可能會出現問題。我重現了錯誤,並且(在我的情況下)修正了它。

我建議你運行OPTIMIZE TABLE命令來重命名列的表。文檔說 - 對於InnoDB表,OPTIMIZE TABLE被映射到ALTER TABLE,它重建表來更新索引統計信息並釋放聚集索引中未使用的空間。


還有一個解決辦法:

刪除引用表中唯一的鍵(即使用外鍵鍵,你的情況是一個主鍵)。然後添加新的外鍵並重新創建被刪除的唯一密鑰。


還有一個解決辦法:

嘗試添加和刪除新列引用的表,然後嘗試創建自己的外鍵。

ALTER TABLE company ADD COLUMN column1 VARCHAR(255) DEFAULT NULL; 
ALTER TABLE company DROP COLUMN column1; 
+0

儘管我從未提及過,但我確實對所有內容進行了優化。不幸的是,這也沒有奏效。 – egervari 2011-04-15 11:05:54

+0

我已經添加了一些註釋。 – Devart 2011-04-15 12:31:05

+0

我不能放下任何鑰匙。這是一個生產數據庫。 :/ – egervari 2011-04-15 13:12:36