Question

J'utilise MySQL et j'ai une table avec un index qui sert de clé étrangère dans beaucoup d'autres tables. Je souhaite modifier le type de données de l'index (de signé à un entier non signé), quel est le meilleur moyen de le faire?

J'ai essayé de modifier le type de données sur le champ d'index, mais cela a échoué car il est utilisé comme clé étrangère pour d'autres tables. J'ai essayé de modifier le type de données sur l'une des clés étrangères, mais cela a échoué car il ne correspond pas au type de données de l'index.

Je suppose que je pourrais supprimer manuellement toutes les contraintes de clé étrangère, modifier les types de données et les rajouter, mais cela représenterait beaucoup de travail, car de nombreuses tables utilisent cet index comme clé étrangère. Existe-t-il un moyen de désactiver temporairement les contraintes de clé étrangère lors d'un changement? De même, existe-t-il un moyen d’obtenir une liste de tous les champs référençant l’index comme une clé étrangère?

Mise à jour: J'ai essayé de modifier la clé étrangère après avoir désactivé les contrôles de clé étrangère, mais cela ne semble pas être en train de désactiver les contrôles:

SET foreign_key_checks = 0;

ALTER TABLE `escolaterrafir`.`t23_aluno` MODIFY COLUMN `a21_saida_id` INTEGER DEFAULT NULL;

Voici l'erreur:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
090506 11:57:34 Error in foreign key constraint of table escolaterrafir/t23_aluno:
there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match to the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:
,
  CONSTRAINT FK_t23_aluno_8 FOREIGN KEY (a21_saida_id) REFERENCES t21_turma (A21_ID)

Définition de la table d'index:

DROP TABLE IF EXISTS `escolaterrafir`.`t21_turma`;
CREATE TABLE  `escolaterrafir`.`t21_turma` (
  `A21_ID` int(10) unsigned NOT NULL auto_increment,
  ...
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1;

et la table contenant la clé étrangère qui pointe vers elle:

DROP TABLE IF EXISTS `escolaterrafir`.`t23_aluno`;
CREATE TABLE  `escolaterrafir`.`t23_aluno` (
  ...
  `a21_saida_id` int(10) unsigned default NULL,
  ...
  KEY `Index_7` (`a23_id_pedagogica`),
  ...
  CONSTRAINT `FK_t23_aluno_8` FOREIGN KEY (`a21_saida_id`) REFERENCES `t21_turma` (`A21_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=387 DEFAULT CHARSET=latin1;
Était-ce utile?

La solution 2

Pour répondre à ma propre question, je ne pouvais pas découvrir un moyen plus simple de procéder. J'ai fini par abandonner toutes les contraintes de clé étrangère, changer les types de champs, puis rajouter toutes les contraintes de clé étrangère.

Comme R. Bemrose l'a noté, l'utilisation de SET, foreign_key_checks = 0; , aide uniquement lors de l'ajout ou de la modification de données, mais n'autorise pas les commandes ALTER TABLE qui rompraient la clé étrangère. contraintes.

Autres conseils

Voici ma petite contribution à ce fil. Merci à Daniel Schneller de m'avoir inspiré et de m'avoir fourni une énorme partie de la solution!

set group_concat_max_len = 2048;
set @table_name = "YourTableName";
set @change = "bigint unsigned";
select distinct table_name,
       column_name,
       constraint_name,
       referenced_table_name,
       referenced_column_name,
       CONCAT(
           GROUP_CONCAT('ALTER TABLE ',table_name,' DROP FOREIGN KEY ',constraint_name SEPARATOR ';'),
           ';',
           GROUP_CONCAT('ALTER TABLE `',table_name,'` CHANGE `',column_name,'` `',column_name,'` ',@change SEPARATOR ';'),
           ';',
           CONCAT('ALTER TABLE `',@table_name,'` CHANGE `',referenced_column_name,'` `',referenced_column_name,'` ',@change),
           ';',
           GROUP_CONCAT('ALTER TABLE `',table_name,'` ADD CONSTRAINT `',constraint_name,'` FOREIGN KEY(',column_name,') REFERENCES ',referenced_table_name,'(',referenced_column_name,')' SEPARATOR ';')
       ) as query
from   INFORMATION_SCHEMA.key_column_usage
where  referenced_table_name is not null
   and referenced_column_name is not null
   and referenced_table_name = @table_name
group by referenced_table_name

En définissant @table_name et @change, vous pouvez générer une requête. @ nom_table doit être un nom de table de la table avec la clé primaire (il recherchera les tables qui utilisent cette colonne comme clé étrangère) et change son type en @change.

J'ai dû changer quelques tables comme ça, alors ça a fonctionné à merveille. Il me suffisait de changer @nom_table, puis d'effectuer une requête.

Pour en savoir plus sur l'utilisation des contraintes de clé étrangère, lancez la requête suivante sur la base de données INFORMATION_SCHEMA :

select distinct table_name, 
       column_name, 
       constraint_name,  
       referenced_table_name, 
       referenced_column_name 
from   key_column_usage 
where  constraint_schema = 'XXX' 
   and referenced_table_name is not null 
   and referenced_column_name is not null;

Remplacez XXX par votre nom de schéma. Cela vous donnera une liste de tables et de colonnes faisant référence à d’autres colonnes en tant que clés étrangères.

Malheureusement, les modifications de schéma ne sont pas transactionnelles. Je crains donc que vous n'ayez en fait à désactiver temporairement le foreign_key_checks pour cette opération. Je recommande - si possible - d'empêcher les connexions de tout client pendant cette phase afin de minimiser le risque d'infractions de contrainte accidentelles.

En ce qui concerne les clés elles-mêmes: elles devront également être supprimées et recréées lorsque vous aurez modifié les types de données de la table.

Vous pouvez désactiver temporairement les clés étrangères en tapant

SET foreign_key_checks = 0;

et pour les réactiver

SET foreign_key_checks = 1;

Je pense que cela nécessite des privilèges d'administrateur, car il est destiné à importer des données dans la base de données.

Modifier : en réaction à votre modification, il semblerait que cette option ne désactive que les contraintes applicables aux instructions DML (insertion, mise à jour, suppression), mais pas les instructions DDL (modification de table, modification de table, etc.). ).

Si vous pouvez arrêter la base de données puis essayez de vider les tables dans un fichier texte, modifiez manuellement la définition des colonnes dans le fichier et importez les tables à nouveau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top