2012-05-31 11 views
11

私のMySQL InnoDBデータベースでは外来キーを使用していましたが、プライマリキーの一部を誤って無署名の代わりに署名しました。MySQLの主キーを署名済みから署名なしに変更するには?

は、今私は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で作業していて、上記のALTER TABLEを実行する前に、

SET foreign_key_checks = 0; 

のステートメントを使用しました。どちらもうまくいきません。 通知:私のすべてのテーブルはまだ空です。まだデータはありません。

データベースには多くのテーブルがあるため、すべての外部キーを削除してから手動で再度追加する必要があります。 (これが理由であれば)。

答えて

9

このフィールドは外部キー(複数可)で使用されてみてください。 MySQLでは、このフィールドを変更するには、次の手順を実行する必要があります。

  • ドロップ、関連するすべての外部キー
  • 修正フィールド
  • を再作成し、すべてが落下外部キー
+0

ありがとうございます。これは動作しますが、雑用です。 – Norwald2

+0

はい、そうです。 [dbForge Studio for MySQL](http://www.devart.com/dbforge/mysql/studio/)のリファクタリングで列の名前を変更することもできます。データベースエクスプローラで自動的に実行されます。 – Devart

+0

私はこのアプローチを使い、プロセス全体をスクリプト化しました。答えはhttps://stackoverflow.com/a/47169383/1241791 – Sam

1

この
ALTER TABLE 'users' MODIFY 'id' UNSIGNED NOT NULL AUTO_INCREMENT'

+0

を使用しても動作しません。 – Norwald2

5

使用してデータベースのダンプを取りますmysqlコマンドmysqldumpを実行し、必要に応じてすべての場所を検索して署名なしの場所に追加します。その後、同じデータベースにダンプを復元します。復元する前にすべてのテーブルを削除してからダンプしてください。

+0

です。外部キーを削除するよりもずっと簡単です。 (あなたがこれを行うことができるなら) – AntonioCS

+0

私の外来キーをすべて再作成する必要がないので、私に多くの時間を節約できました。 –

0

MySQL Workbenchこれを行うことができます。 PRIMARY KEYと、外部キー参照を持つ各テーブルのすべてのカラムを確実に変更する必要があります。

多くのシナリオで動作することがわかりました.YMMV。

0

私はいくつかのプライマリキーと同じ問題が署名されたプロジェクトを引き継いだが、関連する外部フィールドも署名されていた。

私は@Devartアプローチを使用しましたが、私はプロセス全体を自動化することができました。 information_schemaをクエリして追加のSQL文を生成することができました。このSQL文は、「切り取って貼り付け」して後で実行することができます。

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

アルターUNSIGNED

に変更する必要がある任意の id列を削除するSQL文を生成
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ていても により、符号なしには変更されているが、これは何の問題も発生しない)

挿入し直し、必要なすべての制約

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」とみなされるなど、スキーマに合わせて変更する必要があります。

また、実際の出力を実行する前に、これら4つのステートメントのすべてを実行する必要があります。

MySQL 5.6

関連する問題