web-dev-qa-db-fra.com

Mysql delete contrainte

J'ai une table avec la structure ci-dessous:

    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

Je dois supprimer la clé "unique_help", mais je reçois une erreur de contrainte de clé étrangère.

En raison de cette erreur, je ne suis pas en mesure de supprimer quoi que ce soit parmi ceux-ci, Section_constraint, language_constraint, unique_help.

Vous trouverez ci-dessous d'autres tableaux faisant référence à ceci:

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
10
viv

Le problème est que l'index unique_help (section, language) est utilisé par la contrainte de clé étrangère section_constraint. Vous ne pouvez donc pas supprimer l'index sans supprimer d'abord la contrainte.


Une façon de résoudre ce problème consiste à supprimer d'abord la contrainte de clé étrangère, puis à supprimer l'index.

Ensuite, vous pouvez ajouter un index (simple) sur (section) et recréer la clé étrangère.

Tout cela peut être fait en une seule déclaration:

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

Testé àSQL-Fiddle


Amélioration

Je me suis trompé, pas besoin de laisser tomber et de recréer la contrainte. L'index peut être supprimé tant qu'un nouvel index est créé:

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

Testé àSQL-Fiddle-2

19
ypercubeᵀᴹ
ALTER TABLE Orders
DROP FOREIGN KEY 'language_constraint';

ALTER TABLE Orders
DROP FOREIGN KEY 'section_constraint';

EFFECTUER UNE SUPPRESSION ICI

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

Comme votre message d'erreur le suggère :

(...) dans le [table référencée par une clé étrangère] , il doit exister un index dans lequel les colonnes référencées sont répertoriées comme premières colonnes dans identiques ordre.

Vous devez trouver la ou les tables de référence et supprimer la ou les contraintes de clé étrangère de cette (ces) autre (s) table (s). </ Strike>

Mon mauvais, j'ai lu votre définition de table trop rapidement. Le problème actuel est dans l’inverse :

MySQL requiert des index sur les clés étrangères et les clés référencées pour que La vérification des clés étrangères puisse être rapide et ne nécessite pas d'analyse de table.

Supprimez d'abord la contrainte de clé étrangère section_constraint ou créez un nouvel index sur language avant de supprimer la contrainte UNIQUE.

2
RandomSeed

Voici une procédure stockée que vous pouvez appeler pour supprimer une clé étrangère avant d'appeler create SQL. J'ai modifié une réponse à une question similaire à propos de DROP PROCEDURE IF EXISTS Réponse de: https://stackoverflow.com/users/166161/thomas-paine

exemple d'appel:

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

Procédure:

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 ;
1
Big D.