Вопрос

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

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

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

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

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;
Это было полезно?

Решение 2

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

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

Другие советы

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

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, а затем выполнить запрос.

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

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

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

SET foreign_key_checks = 0;

и снова включить их

SET foreign_key_checks = 1;

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

Редактировать:В ответ на вашу правку, похоже, что она отключает ограничения только для операторов DML (insert, update, delete), но не для операторов DDL (alter table, drop table и т.д.).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top