2009-08-24 4 views
14

Dans mySQL 5, existe-t-il un moyen de supprimer toutes les contraintes de clé étrangère sur une table avec une instruction SQL sans les nommer par leur nom? Je suis en train d'écrire un script de mise à jour DB, et malheureusement certains des sites ont des contraintes créées avec des noms "faux". J'essaie d'éviter d'entrer et d'obtenir les noms de contraintes réels de la base de données et de les réinsérer dans des instructions SQL.Est-il possible de supprimer toutes les contraintes de clé étrangère sur une table à la fois dans mySQL 5?

Répondre

6

Vous pouvez certainement sélectionner * la table dans une table temporaire, la supprimer et la recréer, puis la recopier.

+1

Pour me faire erreur comme 'Impossible de supprimer ou mettre à jour une ligne parent: une contrainte de clé étrangère échoue ». J'ai essayé de créer chaque ligne puis seulement pour une ligne d'erreur, d'autres supprimées. – Pramod

+1

"Sûrement" à peine. Dans le monde réel, les tables sont souvent trop grandes pour que cela soit réalisable. N'existe-t-il pas un moyen de manipuler les index sans recréer toute la table? (Oui: voir l'excellente solution de Dandalf!) –

6

Dans votre script, vous pouvez toujours ajouter SET FOREIGN_KEY_CHECKS = 0 si vous voulez juste contourner les contraintes.

Aussi, j'ai toujours contraintes supprimées sur une base par contrainte en utilisant:

ALTER TABLE <table_name> DROP FOREIGN KEY <key_name>; 

Je ne pense pas que vous pouvez faire tous à la fois et je ne pouvais pas trouver des exemples que vous pouvez montrer.

6

Vous pouvez utiliser ce script bash simple:

Run:

sh deleteForeignKeys.sh 

et deleteForeignKeys.sh est

#!/bin/bash 

dbname="databasename" 
table="tablename" 

mysqlconn="mysql -u username -ppassword -h host" 

tableschema=$($mysqlconn -N -e "SHOW CREATE TABLE $dbname.$table") 

#Foreign Keys 
fks=$(echo $tableschema | grep -oP '(?<=CONSTRAINT `).*?(?=` FOREIGN KEY)') 

for fk in $fks; 
do 
    # DROP FOREIGN KEY 
    $mysqlconn -e "ALTER TABLE $dbname.$table DROP FOREIGN KEY $fk"; 
done 
7

Voici une sélection qui crée goutte complète et créer des instructions pour toutes les relations Sur une table. Pas automatique en aucune façon, mais assez facile à copier/coller à partir ..

SELECT `DROP`,`CREATE` FROM (
SELECT 
CONCAT("ALTER TABLE `", `K`.`TABLE_NAME`, "` DROP FOREIGN KEY `", `K`.`CONSTRAINT_NAME`, "`;") "DROP", 
CONCAT("ALTER TABLE `", 
`K`.`TABLE_NAME`, 
"` ADD CONSTRAINT ", 
"`fk_", 
`K`.`TABLE_NAME`, 
"_", 
`K`.`REFERENCED_TABLE_NAME`, 
"1", 
"` FOREIGN KEY (`", 
`K`.`COLUMN_NAME`, 
"`) REFERENCES ", 
"`", 
`K`.`REFERENCED_TABLE_SCHEMA`, 
"`.`", 
`K`.`REFERENCED_TABLE_NAME`, 
"` (`", 
`K`.`REFERENCED_COLUMN_NAME`, 
"`) ON DELETE ", 
`C`.`DELETE_RULE`, 
" ON UPDATE ", 
`C`.`UPDATE_RULE`, 
";") "CREATE" 
FROM `information_schema`.`KEY_COLUMN_USAGE` `K` 
LEFT JOIN `information_schema`.`REFERENTIAL_CONSTRAINTS` `C` USING (`CONSTRAINT_NAME`) 
WHERE `K`.`REFERENCED_TABLE_SCHEMA` = "your_db" 
AND `K`.`REFERENCED_TABLE_NAME` = "your_table") AS DropCreateConstraints 

Je l'ai utilisé pour abandonner toutes les relations, modifier les types de données sur les touches, puis restaurer les relations avec les noms clés étrangers à la MySQL Workbench. Pourrait être utile à quelqu'un ..

11

J'ai une solution similaire à la réponse de Bing, mais il faut aller un peu plus loin pour être automatique et réutilisable dans une procédure.

DROP PROCEDURE IF EXISTS dropForeignKeysFromTable; 

delimiter /// 
create procedure dropForeignKeysFromTable(IN param_table_schema varchar(255), IN param_table_name varchar(255)) 
begin 
    declare done int default FALSE; 
    declare dropCommand varchar(255); 
    declare dropCur cursor for 
     select concat('alter table ',table_schema,'.',table_name,' DROP FOREIGN KEY ',constraint_name, ';') 
     from information_schema.table_constraints 
     where constraint_type='FOREIGN KEY' 
      and table_name = param_table_name 
      and table_schema = param_table_schema; 

    declare continue handler for not found set done = true; 

    open dropCur; 

    read_loop: loop 
     fetch dropCur into dropCommand; 
     if done then 
      leave read_loop; 
     end if; 

     set @sdropCommand = dropCommand; 

     prepare dropClientUpdateKeyStmt from @sdropCommand; 

     execute dropClientUpdateKeyStmt; 

     deallocate prepare dropClientUpdateKeyStmt; 
    end loop; 

    close dropCur; 
end/// 

delimiter ; 

Depuis une déclaration préparée ne peut traiter une instruction à la fois, la procédure des boucles à travers les clés étrangères à l'aide d'un curseur et exécute chaque goutte un à la fois.

Pour utiliser la procédure sur l'un de vos tables il suffit d'utiliser les éléments suivants, en remplacement table_schema et nom_de_table vos valeurs:

call dropForeignKeysFromTable('table_schema', 'table_name'); 
+1

Great Procedure! Fonctionne fantastiquement! – Livewire

+0

C'est ce que je cherchais. Excellent travail Dandalf! –

+0

Fonctionne comme un charme. Merci !! –

Questions connexes