Как изменить основной ключ MySQL от подписанного к unsigned?

В моей базе данных MySQL InnoDB с внешними ключами я случайно сделал некоторые из моих первичных ключей, подписанных вместо unsigned, как я хочу, чтобы они были.

Теперь я хочу изменить его с помощью инструкции ALTER TABLE, но она не работает:

ALTER TABLE `users` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT

Ошибка MySQL:

Error on rename of './db_dev/#sql-478_3' to './db_dev/users' (errno: 150)

Я не понимаю, почему. Я работаю с Foreign Keys и пробовал использовать

SET foreign_key_checks = 0;

Заявление перед выполнением ALTER TABLE сверху. Не работает. Примечание. Все мои таблицы по-прежнему пусты. В нем пока нет данных.

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

Ответ 1

Это поле используется во внешних ключах. Чтобы изменить это поле в MySQL, выполните следующие действия:

  • Отбросить все связанные внешние ключи
  • Изменить поле
  • Восстановить все сброшенные внешние ключи

Ответ 2

Возьмите дамп базы данных с помощью команды mysql mysqldump и выполните поиск и добавьте unsigned в любое место, где это необходимо. Затем восстановите дамп в той же базе данных. Перед восстановлением удалите из него все таблицы и выгрузите их.

Ответ 3

Попробуйте это
ALTER TABLE 'users' MODIFY 'id' UNSIGNED NOT NULL AUTO_INCREMENT'

Ответ 4

MySQL Workbench позволит вам это сделать. Вам необходимо убедиться, что вы изменили PRIMARY KEY и все столбцы в каждой таблице, в которой есть ссылка на внешний ключ.

Я нашел, что он работает над несколькими сценариями, YMMV.

Ответ 5

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

Я использовал подход @Devart, но мне удалось автоматизировать весь процесс. Я смог запросить information_schema для создания дополнительных операторов SQL, которые я мог бы "вырезать и вставить", а затем запустить.

Сгенерировать инструкции SQL для удаления всех ограничений

SELECT concat('ALTER TABLE ', TABLE_NAME, ' DROP FOREIGN KEY ', CONSTRAINT_NAME, ';')
FROM information_schema.key_column_usage
WHERE CONSTRAINT_SCHEMA = 'YOUR_SCHEMA_NAME'
AND referenced_table_name IS NOT NULL;

Изменить любые столбцы id, которые необходимо изменить на UNSIGNED

SELECT
  CONCAT('ALTER TABLE `', TABLE_NAME, '` CHANGE COLUMN  id id INT UNSIGNED NOT NULL AUTO_INCREMENT;')
FROM `COLUMNS`
WHERE
  `COLUMN_KEY` = 'PRI' AND
  `TABLE_SCHEMA` = 'YOUR_SCHEMA_NAME' AND
  `COLUMN_TYPE` NOT LIKE '%unsigned%' AND
  `COLUMN_TYPE` LIKE '%int%' AND
  `COLUMN_NAME` = 'id';

Изменить внешние поля, указывающие на id

SELECT CONCAT('ALTER TABLE `', kcu.TABLE_NAME, '` CHANGE COLUMN  ', kcu.COLUMN_NAME,' ', kcu.COLUMN_NAME, ' INT UNSIGNED ', IF(c.IS_NULLABLE = 'YES', 'NULL', 'NOT NULL'), ';')
FROM `KEY_COLUMN_USAGE`  kcu
INNER JOIN `COLUMNS` c
ON
  kcu.TABLE_NAME = c.TABLE_NAME AND
  kcu.COLUMN_NAME = c.COLUMN_NAME
WHERE
  `REFERENCED_COLUMN_NAME` = 'id' AND
  `REFERENCED_TABLE_NAME` IN (
    SELECT
        TABLE_NAME
    FROM `COLUMNS`
    WHERE
        `COLUMN_KEY` = 'PRI' AND
        `TABLE_SCHEMA` = 'YOUR_SCHEmA_NAME' AND
        `COLUMN_TYPE` NOT LIKE '%unsigned%' AND
        `COLUMN_TYPE` LIKE '%int%' AND
        `COLUMN_NAME` = 'id'
);

(Обратите внимание, что в этом заявлении все по ошибке ошибочно перепутаны  даже если они уже НЕ СУЩЕСТВУЮТ, но это не вызывает никаких проблем)

Вставить все необходимые ограничения

SELECT CONCAT('ALTER TABLE ', rc.`TABLE_NAME` ,' ADD CONSTRAINT ', rc.`CONSTRAINT_NAME`, ' FOREIGN KEY (',kcu.`COLUMN_NAME`,') REFERENCES ', rc.`REFERENCED_TABLE_NAME` ,'(id) ON DELETE ', DELETE_RULE , ' ON UPDATE ' , UPDATE_RULE, ';')
FROM `REFERENTIAL_CONSTRAINTS` rc
INNER JOIN
    `KEY_COLUMN_USAGE` kcu
     ON rc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
WHERE kcu.CONSTRAINT_SCHEMA = 'api'      AND
kcu.`REFERENCED_COLUMN_NAME` = 'id';

Обратите особое внимание на эти операторы SQL, возможно, это необходимо изменить для вашей схемы, например, предполагается, что ваш первичный идентификатор называется "id".

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

Использование MySQL 5.6