问题 如何将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 TABLE之前的语句。也不起作用。 注意:我的所有表都是空的。它还没有数据。

由于数据库有很多表,因此删除所有外键然后再次手动添加它们将会非常有用。 (如果这应该是原因)。


3462
2018-05-31 12:22


起源



答案:


该字段用于外键。要在MySQL中更改此字段,您应该执行以下步骤:

  • 删除所有相关的外键
  • 修改字段
  • 重新创建所有丢弃的外键

9
2018-05-31 12:28



谢谢。这可行,但是是一件苦差事。 - Norwald2
是的。您可以尝试使用重构进行列重命名 dbForge Studio for MySQL;它会自动执行(在数据库资源管理器中)。 - Devart
我使用了这种方法并编写了整个过程的脚本,请参阅答案 stackoverflow.com/a/47169383/1241791 - Sam Anthony


答案:


该字段用于外键。要在MySQL中更改此字段,您应该执行以下步骤:

  • 删除所有相关的外键
  • 修改字段
  • 重新创建所有丢弃的外键

9
2018-05-31 12:28



谢谢。这可行,但是是一件苦差事。 - Norwald2
是的。您可以尝试使用重构进行列重命名 dbForge Studio for MySQL;它会自动执行(在数据库资源管理器中)。 - Devart
我使用了这种方法并编写了整个过程的脚本,请参阅答案 stackoverflow.com/a/47169383/1241791 - Sam Anthony


使用mysql命令mysqldump转储数据库并搜索并在需要的地方添加unsigned。然后将转储还原到同一数据库。在还原之前,从中删除所有表并将其转储。


5
2017-08-10 11:41



比删除外键简单得多。 (如果你能做到这一点) - AntonioCS
不必重新创建我的所有外键给我节省了很多时间。 - Daniel Castro


尝试这个
ALTER TABLE 'users' MODIFY 'id' UNSIGNED NOT NULL AUTO_INCREMENT'


1
2018-05-31 12:26



不起作用。 - Norwald2


我接手了一个项目,该项目签署了一些相同的主键问题,并且相关的外国字段也已签署。

我使用@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'
);

(请注意,在本声明中,所有内容都被错误地更改为UNSIGNED  即使它们已经是UNSIGNED但这不会导致任何问题)

重新插入所有必需的约束

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称为“id”。

此外,在运行任何实际输出之前,必须运行所有这四个语句。

使用MySQL 5.6


1
2017-11-07 23:58





MySQL Workbench 会让你这样做。您需要确保更改PRIMARY KEY和每个具有外键引用的表中的所有列。

我发现它适用于许多场景,YMMV。


0
2017-12-30 11:49





以下内容适用于许多情况,但这取决于列的修改方式

-- disable fk constraints
SET FOREIGN_KEY_CHECKS=0;

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

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

如果它使FK无效,这可能不起作用 - 在这种情况下,您将需要删除/重新创建FK。

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');

0
2017-07-26 11:40



即使代码是解释性的,请添加一些解释。 - Harsha B