Ограничение в 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

4 ответов


проблема в том, что используется 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


ALTER TABLE Orders
DROP FOREIGN KEY 'language_constraint';

ALTER TABLE Orders
DROP FOREIGN KEY 'section_constraint';

ВЫПОЛНИТЬ ЗАПРОС УДАЛЕНИЯ ЗДЕСЬ

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`);

как следует из Вашего сообщения об ошибке:

(...) в [таблицы, на которую ссылается внешний ключ], должен быть индекс, в котором ссылочные столбцы перечислены в качестве первых столбцов в тот же порядок.

вы должны найти ссылочную таблицу(таблицы) и удалить ограничение(ограничения) внешнего ключа из этой (этих) другой таблицы(таблиц).

мой плохой, я слишком быстро прочитал ваше определение таблицы. Этот фактическая проблема наоборот:

MySQL требует индексов на внешних ключах и ссылочных ключах, чтобы проверки внешнего ключа могут быть быстрыми и не требуют сканирования таблицы.

либо падение section_constraint ограничение внешнего ключа сначала или создайте новый индекс на language перед удалением уникального ограничения.


вот хранимая процедура, которую можно вызвать для удаления внешнего ключа перед вызовом create sql. Я изменил ответ на аналогичный вопрос о процедуре DROP, если существует ответ: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 ;