Domanda

Sto usando MySQL e ho una tabella con un indice che viene utilizzata come chiave esterna in molte altre tabelle. Voglio cambiare il tipo di dati dell'indice (da intero con segno a senza segno), qual è il modo migliore per farlo?

Ho provato a modificare il tipo di dati nel campo dell'indice, ma questo non riesce perché viene utilizzato come chiave esterna per altre tabelle. Ho provato a modificare il tipo di dati su una delle chiavi esterne, ma non è riuscito perché non corrispondeva al tipo di dati dell'indice.

Suppongo che potrei eliminare manualmente tutti i vincoli di chiave esterna, modificare i tipi di dati e aggiungere nuovamente i vincoli, ma questo sarebbe molto lavoro perché ho molte tabelle che utilizzano questo indice come chiave esterna. C'è un modo per disattivare temporaneamente i vincoli di chiave esterna mentre si effettua una modifica? Inoltre, c'è un modo per ottenere un elenco di tutti i campi che fanno riferimento all'indice come chiave esterna?

Aggiornamento: Ho provato a modificare una chiave esterna dopo aver disattivato i controlli di chiave esterna, ma non sembra disattivare i controlli:

SET foreign_key_checks = 0;

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

Ecco l'errore:

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

Definizione della tabella dell'indice:

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;

e la tabella con la chiave esterna che punta ad essa:

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;
È stato utile?

Soluzione 2

Per rispondere alla mia domanda, non sono riuscito a scoprire un modo più semplice per farlo. Ho finito per eliminare tutti i vincoli di chiave esterna, modificare i tipi di campo e quindi aggiungere nuovamente tutti i vincoli di chiave esterna.

Come notato da R. Bemrose, l'uso di SET foreign_key_checks = 0; aiuta solo quando si aggiungono o modificano dati, ma non consentono i comandi ALTER TABLE che rompono la chiave esterna vincoli.

Altri suggerimenti

Ecco il mio piccolo contributo a questa discussione. Grazie a Daniel Schneller per l'ispirazione e per avermi fornito una parte enorme della soluzione!

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

Impostando @table_name e @change è possibile generare una query. @table_name dovrebbe essere un nome di tabella della tabella con la chiave primaria (cercherà le tabelle che utilizzano quella colonna come chiave esterna) e cambierà il suo tipo in @change.

Ho dovuto cambiare alcuni tavoli in quel modo, in modo che funzionasse come un fascino. Ho dovuto cambiare @table_name e quindi eseguire una query.

Per informazioni sull'uso dei vincoli di chiave esterna, emettere la seguente query sul database 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;

Sostituisci XXX con il nome del tuo schema. Questo ti darà un elenco di tabelle e colonne che si riferiscono ad altre colonne come chiavi esterne.

Sfortunatamente le modifiche allo schema non sono transazionali, quindi temo che dovrete effettivamente disabilitare temporaneamente Foreign_key_checks per questa operazione. Raccomando, se possibile, di impedire le connessioni da qualsiasi client durante questa fase per ridurre al minimo il rischio di violazioni accidentali dei vincoli.

Per quanto riguarda le chiavi stesse: dovranno essere eliminate e ricreate anche dopo aver modificato i tipi di dati della tabella.

Puoi disabilitare temporaneamente le chiavi esterne digitando

SET foreign_key_checks = 0;

e per riattivarli

SET foreign_key_checks = 1;

Penso che questo richieda i privilegi di amministratore, perché è destinato a importare i dati nel database.

Modifica : in risposta alla tua modifica, sembra che disabiliti solo i vincoli per le istruzioni DML (inserisci, aggiorna, elimina) ma non le istruzioni DDL (modifica tabella, trascina tabella, ecc ... ).

Se è possibile arrestare il database, provare a scaricare le tabelle in file di testo, modificare manualmente la definizione delle colonne nel file e importare nuovamente le tabelle.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top