2013-05-14 90 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 ;