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

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

Теперь я хочу изменить его с помощью оператора 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)

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

SET foreign_key_checks = 0;

оператор перед выполнением таблицы ALTER сверху. Не работает. Уведомление: Все столики пустые. Данных пока нет.

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

6 ответов


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

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

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


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


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

я использовал подход @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


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

Я нашел его для работы над рядом сценариев, YMMV.


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

-- disable fk constraints
SET FOREIGN_KEY_CHECKS=0;

ALTER TABLE 'table' MODIFY 'column'....

-- re-enable fk constraints
SET FOREIGN_KEY_CHECKS=1;

Это может не работать, если это делает FKS недействительным - в этом случае вам нужно будет удалить/воссоздать FKs.

ALTER TABLE 'table' DROP FOREIGN KEY FK_xxxxxxxxxxx;

ALTER TABLE 'table' MODIFY 'column'....

ALTER TABLE 'table'
  add constraint FK_xxxxxxxxxxx
foreign key ('key-column') references 'other table' ('key-column');