mysql Ograniczenie klucza obcego jest nieprawidłowo sformułowanym błędem


173

Mam dwie tabele, table1to tabela nadrzędna z kolumnąID i table2z kolumny IDFromTable1(nie rzeczywista nazwa), kiedy kładę FK na IDFromTable1celu IDw table1pojawia się błąd Foreign key constraint is incorrectly formed error. Chciałbym usunąć rekord tabeli 2, jeśli table1zostanie usunięty. Dzięki za wszelką pomoc

ALTER TABLE `table2`  
   ADD CONSTRAINT `FK1` 
      FOREIGN KEY (`IDFromTable1`) REFERENCES `table1` (`ID`) 
      ON UPDATE CASCADE 
      ON DELETE CASCADE;

Daj mi znać, jeśli potrzebujesz innych informacji. Jestem nowy w mysql


4
Jakiego silnika używasz do swoich tabel? Jaki jest typ table2.IDFromTable1i table1.ID?
Romain

5
Sprawdź również, czy zestawy znaków dla obu tabel są takie same.
Carsten

Oba silniki tabel są w standardzie innoDB. nie jestem pewien, gdzie znaleźć zestawy znaków, a oba są typu char. Identyfikator jest kluczem podstawowym w tabeli1
user516883,

2
Proszę podać definicje tabel dla tabeli 1 i tabeli 2. Jak otrzymałeś ten błąd? Czy używasz narzędzia do tworzenia klucza obcego? Wygląda na to, że nie jest to natywny błąd MySQL.
Devart

@ user516883 - Czy potrzebujesz pomocy, aby uzyskać definicje tabel? W HeidiSQL możesz po prostu kliknąć zakładkę UTWÓRZ kod .
Álvaro González

Odpowiedzi:


422

Napotkałem ten sam problem z HeidiSQL. Otrzymany błąd jest bardzo tajemniczy. Mój problem polegał na tym, że kolumna klucza obcego i kolumna odwołująca się nie były tego samego typu lub długości.

Kolumna klucza obcego to, SMALLINT(5) UNSIGNEDa kolumna, do której się odwołuje - to INT(10) UNSIGNED. Kiedy utworzyłem dla obu dokładnie ten sam typ, tworzenie klucza obcego działało idealnie.


58
Lub może być tak, że wspomniana kolumna nie jest kluczem podstawowym
nawfal

9
Jak dla mnie podobny problem - wskazana tabela jeszcze nie istniała. Ups.
Amalgovinus

5
Całkowicie doświadczyłem tego, co zrobił Jake, ale napotkałem inny problem FK (innego typu) na HeidiSQL. FK na varcharach musi być tym samym zestawieniem. Mam nadzieję, że to pomoże komuś w przyszłości!
cbloss793

10
W moim przypadku było to spowodowane innym kodowaniem i sortowaniem.
Khatri,

1
@nawfal - uważam, że niekoniecznie musi to być klucz podstawowy, ale MUSI mieć indeks. Klucze podstawowe są automatycznie indeksowane.
Itai

48

Miałem ten sam problem podczas tworzenia tabeli nadrzędnej za pomocą MyISAMsilnika. To głupi błąd, który naprawiłem:

ALTER TABLE parent_table ENGINE=InnoDB;

Dziękuję bardzo, oszalałem z tego. Masz pojęcie, dlaczego baza danych nagle zmieniłaby silnik na tabele?
Robert Franklin

28

upewnij się, że kolumny są identyczne (tego samego typu), a jeśli kolumna odniesienia nie jest primary_key, upewnij się, że tak INDEXED.


Zdarzyło mi się nawet, że nie było błędu, ale klucz obcy nie został dodany (1 był, a 1 nie było), ale po dodaniu prostej KEY referencing_column(referencing_column) PRZED definicją obu kluczy obcych zostały one dodane pomyślnie :)
jave.web

2
Mój problem polegał na braku indeksowania kluczy.
Neil Masters

1
Miałem ten problem, a problem polegał na tym, że miałem dwukolumnowy klucz podstawowy i nie możesz użyć drugiej kolumny klucza podstawowego jako klucza obcego. Po prostu dodałem własny indeks dla drugiej kolumny klucza podstawowego i zadziałało.
Firze,

21

Składnia definiowania kluczy obcych jest bardzo wyrozumiała, ale dla każdego, kto się o to potyka, fakt, że klucze obce muszą być „tego samego typu” dotyczy nawet sortowania, a nie tylko typu i długości danych oraz podpisywania bitów.

Nie żebyś mieszał sortowanie w swoim modelu (prawda?), Ale jeśli to zrobisz, upewnij się, że pola klucza podstawowego i obcego mają ten sam typ sortowania w phpmyadmin lub Heidi SQL lub czymkolwiek innym.

Mam nadzieję, że zaoszczędzi to czterech godzin prób i błędów, które mnie to kosztowało.


1
Dzięki! Okazuje się, że mój host online używa silnika ISAM, a dla lokalnego dewelopera używam InnoDB. Kiedy zrobiłem kopię zapasową stołu od gospodarza do lokalnego ... boomu.
Ben

Najnowsze wersje MariaDB wydają się używać utf8_mb4 jako domyślnego zestawu znaków (jeśli nie jest on jawnie ustawiony w konfiguracji serwera), podobnie jak COLLATE utf8mb4_unicode_cimój (nieoczekiwany) problem (na maszynie deweloperskiej).
JonnyJD

13

Miałem ten sam problem, ale rozwiązałem go.

Tylko upewnij się, że kolumna „ID” w „tabeli1” ma UNIKATOWY indeks!

Oczywiście typ i długość kolumn „ID” i „IDFromTable1” w tych dwóch tabelach muszą być takie same. Ale już o tym wiesz.


Uczyniłeś mój dzień.
kevenlolo

1
Miło, że mogłem pomóc! ;)
Renat Gatin

Nie jestem pewien szczegółów, ale miałem klucz złożony z tym błędem, który został naprawiony przez dodanie indywidualnych unikalnych indeksów dla kolumn.
Halvor Holsten Strand

Kolumna, do której się odwołujemy, musi być zindeksowana, nie musi być unikalna (chociaż tak jest zwykle).
Barmar

10

Tylko do ukończenia.

Ten błąd może również wystąpić, jeśli masz klucz obcy z VARCHAR (..) i zestaw znaków w tabeli, do której się odwołuje, różni się od tabeli, do której się odwołuje.

np. VARCHAR (50) w tabeli Latin1 różni się od VARCHAR (50) w tabeli UTF8.


1
Nawet utf8_unicode_ci i utf8_general_ci powodują błąd
leuchtdiode

10

teksty błędów mysql nie pomagają tak bardzo, w moim przypadku kolumna miała ograniczenie „not null”, więc ustawienie „on delete set null” nie było dozwolone


7

jeśli wszystko jest w porządku, po prostu dodaj ->unsigned();na końcuforegin key .

jeśli to nie zadziała, sprawdź typ danych obu pól. muszą być takie same.


5

Miałem ten sam problem, obie kolumny miały wartość INT (11) NOT NULL, ale nie mogę utworzyć klucza obcego. Musiałem wyłączyć sprawdzanie kluczy obcych, aby go pomyślnie uruchomić:

SET FOREIGN_KEY_CHECKS=OFF;
ALTER TABLE ... ADD CONSTRAINT ...
SET FOREIGN_KEY_CHECKS=ON;

Mam nadzieję, że to komuś pomoże.


4
Właściwie to FOREIGN_KEY_CHECKS
Xmanoux

Pomogło mi to przejść dalej, ale w moim problemie brakowało podstawowego indeksu w kolumnie
bumerang.

4

Jeszcze jedna prawdopodobna przyczyna wyświetlenia tego błędu. Kolejność, w jakiej tworzyłem tabele, była nieprawidłowa. Próbowałem odwołać się do klucza z tabeli, która nie została jeszcze utworzona.


4

(Ostatnio ponownie wysłane) Nawet jeśli nazwa pola i typ danych są takie same, ale sortowanie nie jest takie samo, spowoduje to również ten problem.

Na przykład

    NAZWA TBL | TYP DANYCH | PORÓWNANIE        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         utf8_general_ci

Spróbuj zmienić to na

    NAZWA TBL | TYP DANYCH | PORÓWNANIE        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         latin1_general_ci

....

To zadziałało dla mnie.


3

Sprawdź silnik tabel, oba tabele muszą być tym samym silnikiem, który tak bardzo mi pomógł.


Słuszna uwaga! Mam do czynienia z bazą danych Zen Cart w MySQL, której tabele są domyślnie w silniku MyISAM. Dodałem tabelę za pomocą silnika InnoDB i próbowałem dodać ograniczenie klucza obcego z mojej tabeli do podstawowego klucza Zen Cart. Nie udało się z powodu tego niejasnego błędu „nieprawidłowo uformowanego”. Możesz zobaczyć silnik każdego stołu zSHOW TABLE STATUS LIKE 'table_name';
Neek

2

Miałem te same problemy.

Problem polega na tym, że kolumna odniesienia nie jest kluczem podstawowym.

Niech to będzie klucz podstawowy, a problem zostanie rozwiązany.


Nie musi to być PK, może być również UNIKALNE, NIE NULL.
philipxy

Właściwie ... w moim przypadku wystarczyło ustawić normalny typ indeksu.
hendr1x

2

Chociaż inne odpowiedzi są dość pomocne, chciałem również podzielić się moim doświadczeniem.

Napotkałem problem, gdy usunąłem tabelę, do której idodwoływałem się już jako klucz obcy w innych tabelach ( z danymi ) i próbowałem odtworzyć / zaimportować tabelę z kilkoma dodatkowymi kolumnami.

Zapytanie o odtworzenie (wygenerowane w phpMyAdmin) wyglądało następująco:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL,            /* No PRIMARY KEY index */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

... /* SOME DATA DUMP OPERATION */

ALTER TABLE `the_table`
  ADD PRIMARY KEY (`id`), /* PRIMARY KEY INDEX */
  ADD UNIQUE KEY `uk_acu_donor_name` (`name`);

Jak możesz zauważyć, PRIMARY KEYindeks został ustawiony po utworzeniu ( i wstawieniu danych ), które powodowało problem.

Rozwiązanie

Rozwiązaniem było dodanie PRIMARY KEYindeksu w zapytaniu definiującym tabelę dla tego, do idktórego odwoływano się jako klucz obcy, jednocześnie usuwając go z ALTER TABLEczęści, w której ustawiane były indeksy:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL PRIMARY KEY,            /* <<== PRIMARY KEY INDEX ON CREATION */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

U mnie to zadziałało. Martwiłem się, że muszę ponownie zainstalować oprogramowanie;)
Dewlance


1

Spróbuj wykonać następujące czynności:

pokaż stwórz tabelę Parent

// i sprawdź, czy typy dla obu tabel są takie same, np. myISAM lub innoDB itp
// Inne aspekty do sprawdzenia w tym komunikacie o błędzie: kolumny używane jako obce 
klucze muszą być indeksowane, muszą być tego samego typu 
(jeśli np. jeden jest typu smallint (5), a drugi typu smallint (6), 
to nie zadziała), a jeśli są liczbami całkowitymi, powinny być bez znaku.

// lub sprawdź zestawy znaków
pokaż zmienne takie jak „character_set_database”;
pokaż zmienne, takie jak "collation_database";

// edytowano: spróbuj czegoś takiego
ALTER TABLE tabela 2
DODAJ OGRANICZENIE fk_IdTable2
KLUCZ OBCY (Tabela1_Id)
ODNIESIENIA Tabela1 (Tabela1_Id)
W AKTUALIZACJI KASKADY 
NA DELETE CASCADE;

9
Spróbuj uruchomić SHOW ENGINE INNODB STATUS, aby uzyskać więcej informacji na temat błędu
Sudhir Bastakoti,

@SudhirBastakoti - +1! To zrobiło to dla mnie. Szczegóły są pomocne. Był w stanie szybko rozwiązać problem.
Paul Carlton,

1

Miałem ten sam problem z Symfony 2.8.

Nie dostałem tego na początku, ponieważ nie było podobnych problemów z int długością kluczy obcych itp.

Wreszcie musiałem wykonać następujące czynności w folderze projektu. (Restart serwera nie pomógł!)

app/console doctrine:cache:clear-metadata app/console doctrine:cache:clear-query app/console doctrine:cache:clear-result


1

dzięki S Doerin:

„Tylko do uzupełnienia. Ten błąd może również wystąpić, jeśli masz klucz obcy z VARCHAR (..), a zestaw znaków w tabeli, do której się odwołuje, jest inny niż w tabeli, do której się odwołuje. Np. VARCHAR (50) w tabeli Latin1 to inny niż VARCHAR (50) w tabeli UTF8. "

Rozwiązałem ten problem, zmieniając rodzaj znaków w tabeli. kreacja ma latin1, a poprawna to utf8.

dodaj następną linię. DOMYŚLNY ZESTAW ZNAKÓW = utf8;


1

Miałem problemy z używaniem Alter table do dodania klucza obcego między dwiema tabelami, a pomogło mi upewnienie się, że każda kolumna, do której próbowałem dodać relację klucza obcego, została zindeksowana. Aby to zrobić w PHP myAdmin: Przejdź do tabeli i kliknij kartę struktury. Kliknij opcję indeksu, aby zindeksować żądaną kolumnę, jak pokazano na zrzucie ekranu:

wprowadź opis obrazu tutaj

Po zaindeksowaniu obu kolumn, do których próbowałem odwoływać się za pomocą moich kluczy obcych, udało mi się z powodzeniem użyć tabeli alter i utworzyć relację klucza obcego. Zobaczysz, że kolumny są indeksowane jak na poniższym zrzucie ekranu:

wprowadź opis obrazu tutaj

zwróć uwagę, jak kod_zip pojawia się w obu tabelach.


1

Musisz sprawdzić, czy oba są takie same we wszystkich swoich właściwościach, w tym w „Sortowaniu”


1

Używałem heidisql i rozwiązać ten problem miałem aby utworzyć indeks w tabeli odwołuje się wszystkie kolumny są odwoływać.

dodanie indeksu do tabeli Heidisql


To samo dotyczy mysql: InnoDB wymaga indeksów kluczy obcych i kluczy, do których istnieją odniesienia, aby sprawdzanie kluczy obcych było szybkie i nie wymagało skanowania tabeli.
hendr1x

1

Właśnie teraz napotkałem ten sam problem. W moim przypadku wszystko, co musiałem zrobić, to upewnić się, że tabela, do której się odwołuję w kluczu obcym, musi zostać utworzona przed bieżącą tabelą (wcześniej w kodzie). Więc jeśli odwołujesz się do zmiennej (x * 5), system powinien wiedzieć, czym jest x (x musi być zadeklarowane we wcześniejszych wierszach kodu). To rozwiązało mój problem, mam nadzieję, że pomoże to komuś innemu.


Ten sam problem miałem w MariaDB 10.3.18. Używaliśmy wcześniej MySQL i ostrzegaliśmy, że klucz obcy wskazuje na nieistniejącą tabelę.
MarthyM

0

Miałem ten sam problem z migracją Laravel 5.1 Schema Builder z MariaDB 10.1.

Problem polegał na tym, że unignedzamiast unsigned(s brakowało litery) wpisałem podczas ustawiania kolumny.

Po naprawieniu błędu literówki został dla mnie naprawiony.


0

Nawet ja napotkałem ten sam problem z mysql i liquibase. A więc na tym polega problem: Tabela, z której chcesz odwołać się do kolumny innej tabeli, różni się albo w przypadku typu danych, albo pod względem rozmiaru typu danych.

Error appears in below scenario:
Scenario 1:
Table A has column id, type=bigint
Table B column referenced_id type varchar(this column gets the value from the id column of Table A.)
Liquibase changeset for table B:

    <changeset id="XXXXXXXXXXX-1" author="xyz">
            <column name="referenced_id" **type="varchar"**>
        </column>
            </changeset>
    <changeSet id="XXXXXXXXXXX-2" author="xyz">
                <addForeignKeyConstraint constraintName="FK_table_A"
                    referencedTableName="A" **baseColumnNames="referenced_id**"
                    referencedColumnNames="id" baseTableName="B" />
    </changeSet>

Table A changeSet:

    <changeSet id="YYYYYYYYYY" author="xyz">
     <column **name="id"** **type="bigint"** autoIncrement="${autoIncrement}">
                    <constraints primaryKey="true" nullable="false"/>
                </column>
    </changeSet>

Solution: 
correct the type of table B to bigint because the referenced table has type bigint.

Scenrario 2:
The type might be correct but the size might not.
e.g. :
Table B : referenced column type="varchar 50"
Table A : base column type ="varchar 255"

Solution change the size of referenced column to that of base table's column size.

0

Sprawdź, czy nazwa tabeli jest podana w odpowiedniej wielkości (jeśli nazwy tabel w bazie danych uwzględniają wielkość liter). W moim przypadku musiałem się zmienić

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

do

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `CUSTOMER` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

zwróć uwagę na customerzmianę na CUSTOMER.


0

Lub możesz użyć DBDesigner4, który ma interfejs graficzny do tworzenia bazy danych i łączenia ich za pomocą FK. Kliknij prawym przyciskiem myszy swoją tabelę i wybierz „Kopiuj tworzenie SQL tabeli”, co spowoduje utworzenie kodu.

wprowadź opis obrazu tutaj


0

To stary temat, ale coś odkryłem. Podczas budowania środowiska roboczego MySQL pobiera również relacje z drugiej tabeli. po prostu zostaw filary, do których się odnosisz. Wyczyść inne automatycznie dodane kolumny. To działa dla mnie.


0

Mój przypadek był taki, że miałem literówkę we wspomnianej kolumnie:

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( coutry_code );
ERROR 1005 (HY000): Can't create table `blog`.`t_user` (errno: 150 "Foreign key constraint is incorrectly formed")

Komunikat o błędzie jest dość tajemniczy i próbowałem wszystkiego - weryfikowania typów kolumn, sortowania, silników itp.

Zajęło mi trochę czasu, zanim zanotowałem literówkę, a po naprawieniu wszystko działało dobrze:

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( country_code );
Query OK, 2 rows affected (0.039 sec)              
Records: 2  Duplicates: 0  Warnings: 0

0

W obliczu tego problemu pojawił się błąd, gdy umieściłeś klucz podstawowy w innym typie danych, takim jak:

Tabela 1:

 Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('product_name');
        });

Tabela 2:

Schema::create('brands', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('brand_name');
        });

typ danych dla id drugiej tabeli musi być przyrostem


0

Problem jest bardzo prosty do rozwiązania

np: masz dwie tabele z nazwami użytkowników i postami i chcesz utworzyć klucz obcy w tabeli postów i używasz phpMyAdmina

1) w tabeli postów dodaj nową kolumnę ( name : use_id | type : jak id w tabeli użytkownika | Length : jak id w tabeli użytkownika | Domyślnie : NULL | Atrybuty : unsigned | index: INDEX)

2) na karcie Struktura przejdź do widoku relacji ( Nazwa ograniczenia : automatycznie ustawiana przez phpmyAdmin | nazwa kolumny : wybierz identyfikator_użytkownika | tabela : użytkownicy | klucz : id, ...)

Po prostu został rozwiązany

javad mosavi iran / urmia

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.