2013-05-14 89 views
9

我有一個表結構如下:mysql的刪除約束

CREATE TABLE `Lm_help` (
`id` int(10) NOT NULL AUTO_INCREMENT, 
`section` int(10) NOT NULL, 
`language` int(10) NOT NULL, 
`title` varchar(255) NOT NULL, 
`text` text NOT NULL, 
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
PRIMARY KEY (`id`), 
UNIQUE KEY `unique_help` (`section`,`language`), 
KEY `language_constraint` (`language`), 
CONSTRAINT `language_constraint` FOREIGN KEY (`language`) REFERENCES `Lm_languages` (`id`), 
CONSTRAINT `section_constraint` FOREIGN KEY (`section`) REFERENCES `Lm_help_sections` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 

我需要刪除「unique_help」鍵,但我正在逐漸外鍵約束的錯誤。

由於出現此錯誤,我無法刪除其中的任何內容, section_constraint,language_constraint,unique_help。

下面是有關本其它表:

CREATE TABLE `Lm_languages` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`name` varchar(255) NOT NULL, 
`code` varchar(255) NOT NULL, 
`status` int(11) DEFAULT NULL, 
`created_at` datetime NOT NULL, 
`updated_at` datetime NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 




CREATE TABLE `Lm_help_sections` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`name` varchar(255) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 
+0

你得到什麼錯誤到底是什麼? – 2013-05-14 11:37:59

+0

unique_help不是主鍵,它是唯一索引。你遇到了什麼錯誤? – 2013-05-14 11:38:41

+0

無法刪除索引'language_constraint':在外鍵約束中需要 – viv 2013-05-14 11:38:52

回答

19

的問題是unique_help (section, language)索引用於由section_constraint外鍵約束。因此,如果不先刪除約束條件,則不能刪除索引。


解決此問題的一種方法是首先刪除外鍵約束,然後刪除索引。

然後,您可以在(section)上添加(簡單)索引並重新創建外鍵。

所有這些都可以在一個語句來完成:

ALTER TABLE Lm_help 
    DROP FOREIGN KEY section_constraint, -- drop the FK so 
    DROP INDEX unique_help,    -- the index can be dropped 
              -- and then 
    ADD INDEX section_IX (section),  -- add a new index 
    ADD CONSTRAINT section_FK    -- so the FK can be recreated 
     FOREIGN KEY (section) 
     REFERENCES Lm_help_sections (id) 
    ; 

測試在SQL-Fiddle


改進

我錯了,沒有必要刪除並重新創建約束。該指數可以被丟棄,只要新創建索引:

ALTER TABLE Lm_help 
    DROP INDEX unique_help, 
    ADD INDEX section_IX (section) 
    ; 

測試在SQL-Fiddle-2

+0

謝謝,這工作,我使用drop index section_constraint,這不起作用,但放棄外鍵section_constraint工作.......你能解釋我爲什麼? – viv 2013-05-14 11:57:08

+0

這是刪除外鍵約束的語法(在MySQL中)。 – 2013-05-14 11:57:44

2

As your error message suggests

[表外鍵引用]

(...),有必須是 索引,其中參考列被列爲 中第一列的相同順序。

您必須找到引用表並從這(這些)其他表中刪除外鍵約束。

我的不好,我讀了你的表格定義太快了。實際的問題是the other way around

MySQL的需要外鍵和被引用鍵索引,使 外鍵檢查可以快速,不需要表掃描。

要麼先刪除section_constraint外鍵約束,或刪除UNIQUE約束之前創建language的新指標。

+0

你可以看看其他表的結構,我已經使用 – viv 2013-05-14 11:51:21

+0

我的不好,請看看我的新口氣。 – RandomSeed 2013-05-14 11:59:02

+0

沒問題沒關係,問題解決了,謝謝大家... – viv 2013-05-14 11:59:40

6
ALTER TABLE Orders 
DROP FOREIGN KEY 'language_constraint'; 

ALTER TABLE Orders 
DROP FOREIGN KEY 'section_constraint'; 

PERFORM刪除查詢HERE

ALTER TABLE Orders 
ADD CONSTRAINT `language_constraint` 
FOREIGN KEY (`language`) 
REFERENCES `Lm_languages` (`id`); 

ALTER TABLE Orders 
ADD CONSTRAINT `section_constraint` 
FOREIGN KEY (`section`) 
REFERENCES `Lm_help_sections` (`id`); 
+1

謝謝tushar那個工作,但我不能接受兩個答案...... :) – viv 2013-05-14 11:57:52

+0

沒問題,我很高興我的代碼幫你:) – 2013-05-14 12:10:12

1

這裏是你可以打電話外鍵之前調用創建SQL拋棄存儲過程。我修改回答類似的問題有關DROP PROCEDURE是否存在通過回答:https://stackoverflow.com/users/166161/thomas-paine

調用示例:

CALL DropForeignKey (DATABASE(), 'tablename', 'keyname'); 

步驟:

DELIMITER ; 

/* DROP_FOREIGN_KEY */ 
DROP PROCEDURE IF EXISTS DropForeignKey; 

DELIMITER // 

CREATE PROCEDURE DropForeignKey(
IN param_schema VARCHAR(100), 
IN param_table_name VARCHAR(100), 
IN param_constraint_name VARCHAR(100) 
) 

BEGIN 
    IF EXISTS(
    SELECT NULL FROM information_schema.TABLE_CONSTRAINTS 
    WHERE CONSTRAINT_NAME=param_constraint_name AND TABLE_NAME=param_table_name AND TABLE_SCHEMA = param_schema 
    ) 
    THEN 
     set @paramTable = param_table_name ; 

    set @ParamConstraintName = param_constraint_name ; 
    set @ParamSchema = param_schema; 
    /* Create the full statement to execute */ 
    set @StatementToExecute = concat('ALTER TABLE `',@ParamSchema,'`.`',@paramTable,'` DROP FOREIGN KEY `',@ParamConstraintName,'` '); 
    /* Prepare and execute the statement that was built */ 
    prepare DynamicStatement from @StatementToExecute ; 
    execute DynamicStatement ; 
    /* Cleanup the prepared statement */ 
    deallocate prepare DynamicStatement ; 

END IF; 
END // 

DELIMITER ;