2015-07-15 10 views
6

Mam tabeli, która ma poniżej definicji schematu:nie można zmienić klucza podstawowego powodu „nieprawidłowo utworzonego ograniczenie klucza obcego” błąd

CREATE TABLE `currency` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `code` char(3) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `code_UNIQUE` (`code`) 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 

Co chcę jest spadek kolumnę id i uczynić code jak nowa główny klucz. A niektóre inne tabele mają zagraniczne klucze do tego stołu. I próbował polecenia poniżej, ale nie powiodło się:

SET FOREIGN_KEY_CHECKS=0; 
ALTER TABLE `currency` CHANGE COLUMN `id` `id` INT(11) NOT NULL, DROP PRIMARY KEY; 
ALTER TABLE currency ADD PRIMARY KEY (code); 
SET FOREIGN_KEY_CHECKS=1; 

MySQL zgłasza wyjątek poniżej:

[błąd w zapytaniu 2] błąd na zmiany nazwy z './db/#sql-849_1' do'./db/currency '(errno: 150 - Ograniczenie klucza obcego jest niepoprawnie utworzone) Wykonanie zatrzymane!

Odpowiedz

9

Błąd

Błąd na zmieniły nazwy ... errno: 150 - Klucz obcy ograniczeniem jest nieprawidłowo uformowane)

dzieje się dlatego, że starają się zrzucić odwołuje klucz podstawowy, mimo że wyłączasz sprawdzanie ograniczeń kluczy obcych za pomocą SET FOREIGN_KEY_CHECKS=0;

Wyłączenie sprawdzania kluczy obcych umożliwiłoby tymczasowe usunięcie wiersza w currency lub dodaj nieprawidłowy currencyId w tabelach kluczy obcych, ale nie upuszczaj klucza podstawowego.

Zmiana klucza podstawowego, który jest już przywoływany przez inne tabele, nie będzie prosta, ponieważ ryzykujesz utratę integralności referencyjnej między tabelami i utratę relacji między danymi.W celu ochrony danych, musisz procesu, takie jak:

  • Dodaj nową kolumnę klucza obcego (code) do każdej tabeli FK
  • Mapowanie code klucz obcy z poprzedniego currencyId poprzez aktualizację
  • Usuń istniejący klucz obcy
  • upuść stary currencyId kolumna klucz obcy
  • Gdy wszystkie FK zostały upuszczone zmienić klucz podstawowy w tabeli currency
  • odnowienia kluczy obcych w oparciu o nową code kolumnie

Poniższa zrobiłby to bez konieczności wyłączania FOREIGN_KEY_CHECKS, ale klucz obcy mapy/spadek/odtworzyć krok musiałyby być powtarzane dla wszystkich tabel przedstawieniu currency :

-- Add new FK column 
ALTER TABLE FKTable ADD currencyCode char(3) 
         CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL; 
-- Map FK column to the new Primary Key 
UPDATE FKTable 
    SET currencyCode = (SELECT `code` FROM currency WHERE id = FKTable.currencyId); 
-- Drop the old foreign key + column 
ALTER TABLE FKTable DROP FOREIGN KEY FKTable_Currency; 
ALTER TABLE FKTable DROP COLUMN currencyId; 
-- Once the above is done for all FK tables, drop the PK on currency 
ALTER TABLE `currency` CHANGE COLUMN `id` `id` INT(11) NOT NULL, 
                 DROP PRIMARY KEY; 
ALTER TABLE currency ADD PRIMARY KEY (`code`); 
ALTER TABLE FKTable ADD CONSTRAINT FKTable_Currency2 
      FOREIGN KEY (currencyCode) REFERENCES currency(`code`); 

SqlFiddle here

+1

To bardzo mi pomogło. Dzięki. +1 – Trying

+0

W moim przypadku utworzyłem indeks 'unique', a następnie nie mogłem go upuścić. Najpierw musiałem utworzyć klucz "primary", a potem upuścić ten unikatowy. – Esamo

3

Running

ALTER TABLE myTable DROP PRIMARY KEY; 

spowodował błąd jak

`Error Code: 1025. Error on rename of 'some_name' to 'another_name' (errno: 150 - Foreign key constraint is incorrectly formed)` 

spada, tworząc nową kolumnę i dodanie go jako klucza podstawowego wszystkich za pomocą jednego polecenia działa jak czar.

Nawet ja nie znam przyczyny, jest to ostateczne rozwiązanie wpadłem do:

-- Suppose c1 and c2 are a composite primary key and 
-- I want to add an incremental primary key named id 
ALTER TABLE myTable 
    DROP PRIMARY KEY, 
    ADD id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST, 
    ADD INDEX `an_index_name_for_c1_c2` (`c1`, `c2`); 

Zauważ, że dla dobra wydajność starszych kod, dodaję poprzedniego związku kolumn klucza głównego jako nowy indeks złożony.

Powiązane problemy