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