MySQL изменить тип внешнего ключа
Я использую MySQL и у меня есть таблица с индексом, который используется в качестве внешнего ключа в других таблицах. Я хочу изменить тип данных индекса (от signed до unsigned integer), каков наилучший способ сделать это?
Я попытался изменить тип данных в поле индекса, но это не удалось, потому что он используется в качестве внешнего ключа для других таблиц. Я попытался изменить тип данных на одном из внешних ключей, но это не удалось, потому что он не соответствовал типу данных индекса.
Я полагаю, что я мог бы вручную удалить все ограничения внешнего ключа, изменить типы данных и добавить ограничения обратно, но это было бы много работы, потому что у меня много таблиц, использующих этот индекс в качестве внешнего ключа. Есть ли способ временно отключить ограничения внешнего ключа при внесении изменений? Кроме того, есть ли способ получить список всех полей, ссылающихся на индекс как на внешний ключ?
обновление: Я попытался изменить один иностранный ключ после выключения проверки внешнего ключа, но он, похоже, не отключает проверки:
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;
5 ответов
чтобы ответить на мой собственный вопрос, я не мог найти более простой способ сделать это. В итоге я отбросил все ограничения внешнего ключа, изменил типы полей, а затем добавил все ограничения внешнего ключа обратно.
Как отметил Р. Bemrose, используя 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 `id` `id` ',@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 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, а затем выполнить запрос.
Вы можете временно отключить внешние ключи, введя
SET foreign_key_checks = 0;
и восстановить их
SET foreign_key_checks = 1;
Я думаю, что для этого требуются права администратора, потому что он предназначен для импорта данных в базу данных.
редактировать: в ответ на ваше редактирование, похоже, что он отключает ограничения только для операторов DML (insert, update, delete), но не для операторов DDL (alter table, drop table и т. д...).
Если вы можете остановить базу данных, попробуйте таблицы дампа в текстовый файл, измените определение столбцов вручную в файле и импортируйте таблицы обратно.