MySQL изменяет тип внешнего ключа

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

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

Я полагаю, что я мог бы вручную удалить все ограничения внешнего ключа, изменить типы данных и добавить ограничения назад, но это было бы большой частью работы, потому что у меня много таблиц, использующих этот индекс в качестве внешнего ключа. Есть ли способ временно отключить ограничения внешнего ключа при внесении изменений? Кроме того, есть ли способ получить список всех полей, ссылающихся на индекс, как на внешний ключ?

Update: Я попытался изменить один внешний ключ после отключения проверки внешнего ключа, но, похоже, он не отключает проверки:

SET foreign_key_checks = 0;

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

Здесь ошибка:

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

Определение таблицы индексов:

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;

и таблицу с внешним ключом, которая указывает на нее:

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;

Ответ 1

Чтобы ответить на мой собственный вопрос, я не мог найти более простой способ сделать это. Я закончил сбрасывать все ограничения внешнего ключа, меняя типы полей, а затем добавляя все ограничения внешнего ключа.

Как заметил Р.Бемроуз, использование SET foreign_key_checks = 0; помогает только при добавлении или изменении данных, но не позволяет командам ALTER TABLE нарушать ограничения внешнего ключа.

Ответ 2

Вот мой маленький вклад в эту тему. Спасибо Дэниелу Шнеллеру за вдохновение и за то, что он дал мне большую часть решения!

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

Установив @table_name и @change, вы можете сгенерировать запрос. @table_name должно быть именем таблицы с первичным ключом (он будет искать таблицы, использующие этот столбец в качестве внешнего ключа) и изменить его тип на @change.

Мне пришлось поменять несколько столов, чтобы это работало как шарм. Я просто должен был изменить @table_name и затем выполнить запрос.

Ответ 3

Чтобы узнать об использовании ограничений внешнего ключа, выполните следующий запрос в базе данных 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;

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

К сожалению, изменения схемы не являются транзакционными, поэтому, боюсь, вам действительно придется временно отключить foreign_key_checks для этой операции. Я рекомендую - если возможно - предотвращать соединения с любыми клиентами на этом этапе, чтобы свести к минимуму риск случайных нарушений ограничений.

Что касается самих ключей: их нужно будет удалить и воссоздать, когда вы изменили типы данных таблицы.

Ответ 4

Вы можете временно отключить внешние ключи, набрав

SET foreign_key_checks = 0;

и для их повторного использования

SET foreign_key_checks = 1;

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

Изменить. В ответ на ваше редактирование выглядит так, что он отключает ограничения для операторов DML (вставка, обновление, удаление), но не инструкции DDL (изменить таблицу, таблицу перетаскивания и т.д.).).

Ответ 5

Если вы можете остановить базу данных, тогда попробуйте использовать дамп-таблицы в текстовом файле, измените определение столбцов вручную в файле и верните таблицы импорта.