Migracja: Nie można dodać ograniczenia klucza obcego

207

Próbuję utworzyć klucze obce w Laravel, ale kiedy migruję tabelę przy użyciu, artisanwyświetlany jest następujący błąd:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `priorities` add constraint priorities_user_id_foreign foreign 
key (`user_id`) references `users` (`id`))     

Mój kod migracji jest taki:

plik migracji priorytetów

public function up()
{
    //
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}

plik migracji użytkowników

public function up()
{
    //
    Schema::table('users', function($table)
    {
    $table->create();
    $table->increments('id');
    $table->string('email');
    $table->string('first_name');
    $table->string('password');
    $table->string('email_code');
    $table->string('time_created');
    $table->string('ip');
    $table->string('confirmed');
    $table->string('user_role');
    $table->string('salt');
    $table->string('last_login');

    $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
        Schemea::drop('users');
}

Wszelkie pomysły na to, co zrobiłem źle, chcę to teraz uzyskać, ponieważ mam wiele tabel, które muszę utworzyć, np. Użytkownicy, Klienci, Projekty, Zadania, Statusy, Priorytety, Typy, Zespoły. Idealnie chcę tworzyć tabele, które przechowują te dane z kluczy obcych, i..e clients_projecti project_tasksetc.

Mam nadzieję, że ktoś pomoże mi zacząć.

001221
źródło

Odpowiedzi:

356

Dodaj go w dwóch krokach i dobrze, aby nie był podpisany:

public function up()
{
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id')->unsigned();
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });

   Schema::table('priorities', function($table) {
       $table->foreign('user_id')->references('id')->on('users');
   });

}
Antonio Carlos Ribeiro
źródło
117
Dzięki, Antonio! Dla mnie problemem nie było dodanie unsigned () do kolumny user_id, aby pasował do typu danych kolumny id w tabeli użytkowników. Funkcja inkrementów („id”) Laravela tworzy całkowitą liczbę bez znaku, więc kolumna klucza obcego również musi być bez znaku.
Brad Griffith,
7
Schema::tablepomogło dodawanie bez znaku, oprócz separacji do metody! Dzięki!
patrickjason91
4
Dla mnie nie oznaczało to również, że identyfikator był niepodpisany. Dzięki za wskazówkę.
Carl Weis
6
Rozwiązanie znajduje się w komentarzu @BradGriffith. Jak wspomniano powyżej, nie trzeba wcale się rozdzielać. Może lepiej odpowiednio zaktualizować odpowiedź.
Matanya,
11
Użyj, $table->unsignedBigInteger('user_id')jeśli twój user.id tobigIncrements
Maksim Iwanow
114

Pytanie już zostało udzielone, ale mam nadzieję, że może to pomóc komuś innemu.

Ten błąd wystąpił dla mnie, ponieważ najpierw utworzyłem tabelę migracji z kluczem obcym, zanim klucz istniał jako klucz podstawowy w oryginalnej tabeli. Migracje są wykonywane w kolejności, w jakiej zostały utworzone, zgodnie z nazwą pliku wygenerowaną po uruchomieniu migrate:make. Np 2014_05_10_165709_create_student_table.php.

Rozwiązaniem było zmienić nazwę pliku z kluczem obcym na wcześniejszy niż plik z kluczem podstawowym, zgodnie z zaleceniami tutaj: http://forumsarchive.laravel.io/viewtopic.php?id=10246

Myślę, że musiałem również dodać $table->engine = 'InnoDB';

haakym
źródło
4
Po zmianie nazwy pliku migracji i pojawieniu się błędów, takich jak: Nie można otworzyć strumienia: Nie ma takiego pliku lub katalogu (i wyświetlana jest stara nazwa migracji), należy uruchomić: kompozytor dump-autoload
Stelian
14
$ table-> engine = 'InnoDB'; jest wymagany do wymuszenia klucza obcego na poziomie MySql. Domyślnym silnikiem laravel jest MyIsam, który nie obsługuje kluczy obcych!
François Breton
2
to również działało dla mnie, dzięki. Ale wydaje mi się trochę dziwne, że tak działa. Mam na myśli, że ma to sens, ale powinien istnieć sposób, aby określić kolejność wykonywania migracji inną niż ręczna zmiana nazwy plików i wymyślanie fałszywych dat w tym procesie
allisius
2
Przybyłem tu nie dlatego, że otrzymywałem błędy, ale mogłem dodać nieprawidłowe wartości do kolumny, która była kluczem obcym. Potem zobaczyłem komentarz i odpowiedź na temat InnoDB. To było dobrze wiedzieć. Dzięki chłopaki :)
SuperNOVA,
2
Kolejność tworzenia migracji nadal pozostaje ważna podczas migracji. Natknąłem się na ten problem, ale to rozwiązało.
mugabits
60

Laravel ^ 5.8

Od wersji Laravel 5.8 kody pośredniczące migracji domyślnie używają metody bigIncrements w kolumnach identyfikatorów. Wcześniej kolumny identyfikacyjne były tworzone przy użyciu metody przyrostowej.

Nie wpłynie to na żaden istniejący kod w twoim projekcie; należy jednak pamiętać, że kolumny klucza obcego muszą być tego samego typu . Dlatego kolumna utworzona za pomocą metody przyrostowej nie może odwoływać się do kolumny utworzonej za pomocą metody bigIncrements.

Źródło: Migracje i duże wzrosty


Przykład

Wyobraźmy sobie, że budujesz prostą aplikację opartą na rolach i musisz odwoływać się do user_id w tabeli PIVOT „role_user” .

2019_05_05_112458_create_users_table.php

// ...

public function up()
{
    Schema::create('users', function (Blueprint $table) {

        $table->bigIncrements('id');

        $table->string('full_name');
        $table->string('email');
        $table->timestamps();
    });
}

2019_05_05_120634_create_role_user_pivot_table.php

// ...

public function up()
{
    Schema::create('role_user', function (Blueprint $table) {

        // this line throw QueryException "SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint..."
        // $table->integer('user_id')->unsigned()->index();

        $table->bigInteger('user_id')->unsigned()->index(); // this is working
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    });
}

Jak widać, skomentowany wiersz zgłosi wyjątek zapytania, ponieważ, jak wspomniano w uwagach dotyczących aktualizacji, kolumny klucza obcego muszą być tego samego typu , dlatego należy zmienić klucz prognostyczny (w tym przykładzie jest to identyfikator_użytkownika ) na bigInteger w tabeli rola_użytkownika lub zmień metodę bigIncrements na metodę inkrementacji w tabeli użytkowników i użyj komentowanego wiersza w tabeli przestawnej, to zależy od Ciebie.


Mam nadzieję, że udało mi się wyjaśnić ten problem.

chebaby
źródło
1
Dziękuję Ci. Uratowałeś mi życie. Po wyjaśnieniu zmieniłem mój klucz obcy na bigInteger, jak sugerowałeś. Schema::table('goal_objective', function (Blueprint $table) { $table->bigInteger('job_title_id')->after('target')->unsigned()->nullable(); $table->foreign('job_title_id')->references('id')->on('job_titles')->onDelete('set null'); } Zadziałało. Dziękuję Ci.
Bruce Tong,
1
@BruceTong, cieszę się, że mogłem pomóc.
chebaby
1
Tak, to jest najbardziej odpowiednia odpowiedź.
Mohd Abdul Mujib
1
Ta odpowiedź jest bardzo pomocna.
Karim Pazoki,
1
Najlepsza odpowiedź. Dziękuję
VishalParkash
49

W moim przypadku problem polegał na tym, że główna tabela zawierała już rekordy i zmuszałem nową kolumnę, aby nie miała wartości NULL. Więc dodanie -> nullable () do nowej kolumny załatwiło sprawę. W przykładzie pytania byłoby coś takiego:

$table->integer('user_id')->unsigned()->nullable();

lub:

$table->unsignedInteger('user_id')->nullable();

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

AdrianCR
źródło
Pamiętaj, że kolumna „id” w tabeli nadrzędnej również musi być bez znaku! Użycie wiersza takiego jak $ table-> increments ('id'); automatycznie przejdzie w tryb bez znaku.
Colin Stadig
To zadziałało dla mnie. Zmieniłem typ danych identyfikatora tabeli nadrzędnej z BigIncrements na przyrosty.
Emmanuel Benson,
22

W moim przypadku problemem było ustawienie automatycznej generacji migracji dla userstabeli

...
$table->bigIncrements('id');
...

Musiałem więc zmienić typ kolumny


$table->bigInteger('id');

aby moja migracja z kluczem obcym działała.

To z laravelem 5.8.2

Daniele
źródło
Ponieważ kolumna z kluczem obcym musi mieć ten sam typ kolumny, do której się odnosi
Daniele
9
To działało dla mnie $ table-> unsignedBigInteger ('user_id'); in laravel 5.8. *
Adam Winnipass
Miałem również ten problem z 5.8, to naprawiło to dla mnie! Dzięki!
Mike Sheward,
Uratował mnie od długiej nocy!
str
19

W moim przypadku problem polegał na tym, że podczas migracji należy zachować ostrożność podczas tworzenia migracji. Najpierw utwórz migrację potomną niż migrację podstawową. Ponieważ jeśli najpierw utworzysz migrację podstawową, która ma klucz obcy, poszuka tabeli podrzędnej, a nie będzie tabeli, która następnie wygeneruje wyjątek.

Ponadto:

Podczas tworzenia migracji na początku ma znacznik czasu. powiedzmy, że utworzyłeś kota migracji, więc będzie wyglądać 2015_08_19_075954_the_cats_time.phpi ma ten kod

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TheCatsTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cat', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');  
            $table->date('date_of_birth');
            $table->integer('breed_id')->unsigned()->nullable(); 
        });

        Schema::table('cat', function($table) {
        $table->foreign('breed_id')->references('id')->on('breed');
      });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('cat');
    }
}

Po utworzeniu tabeli podstawowej tworzysz kolejną rasę migracji, która jest tabelą podrzędną, która ma własny znacznik czasu i daty utworzenia. Kod będzie wyglądał następująco:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class BreedTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('breed', function (Blueprint $table) {
             $table->increments('id');    
             $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('breed');
    }
}

Wygląda na to, że obie tabele są poprawne, ale po uruchomieniu migracji rzemieślnika php . Zgłasza wyjątek, ponieważ migracja najpierw utworzy tabelę bazową w bazie danych, ponieważ najpierw utworzyłeś tę migrację, a nasza tabela bazowa zawiera ograniczenie klucza obcego, które będzie szukało tabeli potomnej, a tabela potomna nie istnieje, co prawdopodobnie wyjątek..

Więc:

Najpierw utwórz migrację tabeli podrzędnej.

Utwórz migrację tabeli podstawowej po utworzeniu migracji podrzędnej.

migracja rzemieślnika php.

zrobione to zadziała

Vicky
źródło
13

W moim przypadku po prostu zmieniam, że migracje zamówień są wykonywane ręcznie, więc użytkownicy tabeli są najpierw tworzeni.

W bazie danych folderów / migracje / nazwa pliku migracji ma następujący format: rok_miesiąc_dzien_godz. Godz. Tworzenia_XXXX_tabela.php

Wystarczy zmienić nazwę utwórz plik użytkownika, aby data utworzenia tabeli priorytetów tabeli została ustawiona później niż data użytkownika (wystarczy nawet sekunda później)

ldt
źródło
13

W laravel 5.8 tabela users_table używa bigIncrements('id')typu danych dla klucza podstawowego. Aby więc odwołać ograniczenie klucza obcego, user_idkolumna musi być unsignedBigInteger('user_id')typu.

Dhara Talaviya
źródło
dziękuję bardzo, spędziłem godzinę próbując dowiedzieć się, dlaczego klucz obcy powoduje wyjątek
Ya Basha
10

Miałem ten sam problem podczas korzystania z Laravel 5.8. Po bliższym przyjrzeniu się dokumentom laravel, ponadto tutaj Migracje i duże zmiany . Rozwiązałem to, dodając klucze podstawowe „$ table-> bigIncrements ('id')” do każdej tabeli powiązanej z tabelą „users” i jej powiązaniami, w moim przypadku z tabelą „rola” . Na koniec miałem „$ table-> unsignedBigInteger” do kojarzenia ról z użytkownikami (Many-to-Many), to znaczy w tabeli „rola_użytkownika” .

1. Users table

    Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

2. Roles Table
    Schema::create('roles', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->unique();
        $table->string('display_name')->nullable();
        $table->string('description')->nullable();
        $table->timestamps();
    });

3. Table role_user
Schema::create('role_user', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('role_id');
            $table->foreign('user_id')->references('id')->on('users')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->primary(['user_id', 'role_id']);
        });
Capfer
źródło
9

Miałem ten problem z laravel 5.8 i naprawiłem ten kod, jak pokazano tutaj w dokumentacji Laravel , tam, gdzie kiedykolwiek dodałem klucz obcy.

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

potem pobiegłem $ php artisan migrate:refresh

Ponieważ ta składnia jest dość szczegółowa, Laravel zapewnia dodatkowe, zwięzłe metody, które wykorzystują konwencję, aby zapewnić lepsze wrażenia programistyczne. Powyższy przykład można zapisać następująco:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
});
Slycreator
źródło
7

Korzystanie z Laravel 5.3 miało ten sam problem.

Rozwiązaniem było użycie unsignedInteger zamiast liczby całkowitej ('name') -> unsigned () .

Więc to działało

$table->unsignedInt('column_name');
$table->foreign('column_name')->references('id')->on('table_name');

Powodem tego było to, że podczas używania liczby całkowitej („nazwa”) -> bez znaku kolumna utworzona w tabeli miała długość 11, ale podczas używania liczby całkowitej bez znaku („nazwa”) kolumna miała długość 10.

Długość 10 to długość kluczy podstawowych, gdy używany jest Laravel, więc długość kolumn jest dopasowana.

Radu Diță
źródło
Człowieku, dziękuję za to, że właśnie się poddałem i uruchomiłem surowe narzędzie sql, gdy właśnie znalazłem twój post. Będę musiał przeczytać więcej o tym, dlaczego klucz podstawowy laravel ma mieć długość 10 i jeśli istnieje jakikolwiek powód, dla którego wykonywanie liczb całkowitych („kolumna”) -> unsigned () powinno różnić się od unsigedInteger („kolumna”)
Arnaud Bouchot,
6

Ten błąd wystąpił dla mnie, ponieważ - podczas gdy tabelę, którą próbowałem utworzyć, był InnoDB - tabela zagraniczna, z którą próbowałem ją powiązać, była tabelą MyISAM!

bagnap
źródło
MyISAM nie obsługuje ograniczeń klucza obcego. Prawdopodobnie zadziałało, ponieważ przejście na MyISAM spowodowało, że całkowicie zignorował klucz obcy, który prawdopodobnie był tam z jakiegoś powodu. Bądź ostrożny.
greggle138,
5

Nie możemy dodawać relacji, chyba że zostaną utworzone powiązane tabele. Laravel uruchamia migrację według daty plików migracji. Jeśli więc chcesz utworzyć relację z tabelą, która istnieje w drugim pliku migracji, nie powiedzie się.

Napotkałem ten sam problem, więc w końcu utworzyłem jeszcze jeden plik migracji, aby określić wszystkie relacje.

Schema::table('properties', function(Blueprint $table) {
        $table->foreign('user')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('area')->references('id')->on('areas')->onDelete('cascade');
        $table->foreign('city')->references('id')->on('cities')->onDelete('cascade');
        $table->foreign('type')->references('id')->on('property_types')->onDelete('cascade');
    });

    Schema::table('areas', function(Blueprint $table) {
        $table->foreign('city_id')->references('id')->on('cities')->onDelete('cascade');
    });
pavan kumar
źródło
1
jak nazwałeś plik? 9999_99_99_999999_create_foreign_keys.php?
Iannazzi,
dodanie 9999_99_99_99999 do nazwy pliku migracji jest złym pomysłem, ponieważ zepsuje funkcję przywracania.
Maulik Gangani
5

Pamiętaj: kiedy Laravel ustawia stół, używając

$table->increments('id');

co jest standardem w większości migracji, spowoduje to ustawienie pola liczb całkowitych bez znaku. Dlatego podczas tworzenia odniesienia zagranicznego z innej tabeli do tego pola, upewnij się, że w tabeli odwołań ustawiłeś pole na UnsignedInteger, a nie (jakbym to było) UnsignedBigInteger.

Na przykład: w pliku migracji 2018_12_12_123456_create_users_table.php:

Schema::create('users', function (Blueprint $table){
    $table->increments('id');
    $table->string('name');
    $table->timestamps();

Następnie w pliku migracji 2018_12_12_18000000_create_permissions_table.php, który konfiguruje odniesienia zagraniczne dla użytkowników:

Schema::create('permissions', function (Blueprint $table){
    $table->increments('id');
    $table->UnsignedInteger('user_id'); // UnsignedInteger = "increments" in users table
    $table->boolean('admin');
    $table->boolean('enabled');
    $table->timestamps();

    // set up relationship
    $table->foreign('user_id')->reference('id')->on('users')->onDelete('cascade');
}
bnoeafk
źródło
5

Powinieneś pisać w ten sposób

public function up()
{
    Schema::create('transactions', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->float('amount', 11, 2);
        $table->enum('transaction type', ['debit', 'credit']);
        $table->bigInteger('customer_id')->unsigned();      
        $table->timestamps();                 
    });

    Schema::table('transactions', function($table) {
        $table->foreign('customer_id')
              ->references('id')->on('customers')
              ->onDelete('cascade');
    });     
}

Pole klucza obcego powinno być niepodpisane , mam nadzieję, że to pomoże !!

Mahesh Yadav
źródło
Nie tylko unsigned ale gdy odwołuje się do kolumny bigIncrements powinno być unsigedBigInteger
Gondwe
4

Aby dodać ograniczenie klucza obcego w laravel, działało dla mnie:

  1. Utwórz kolumnę jako klucz obcy w następujący sposób:

    $ table-> integer ('nazwa_kolumny') -> unsigned ();
  2. Dodanie linii ograniczenia bezpośrednio po (1) tj

    $ table-> integer ('nazwa_kolumny') -> unsigned ();
    $ table-> Foreign ('nazwa_kolumny') -> referencje ('pk_of_other_table') -> on ('other_table');
bmnepali
źródło
3

wiem, że to stare pytanie, ale upewnij się, że jeśli pracujesz z referencjami, zdefiniowano odpowiedni silnik pomocniczy. ustaw silnik innodb dla obu tabel i ten sam typ danych dla kolumn referencyjnych

$table->engine = 'InnoDB';
di3
źródło
2

Wchodząc tutaj kilka lat po pierwotnym pytaniu, używając laravel 5.1, miałem ten sam błąd, ponieważ moje migracje były generowane komputerowo z tym samym kodem daty. Przejrzałem wszystkie zaproponowane rozwiązania, a następnie przebudowałem, aby znaleźć źródło błędu.

Uważam, że w kolejnych larakastach i podczas czytania tych postów poprawna odpowiedź jest podobna do odpowiedzi Vickies, z tym wyjątkiem, że nie trzeba dodawać osobnego wywołania schematu. Nie musisz ustawiać tabeli na Innodb, zakładam, że teraz robi to Laravel.

Migracje muszą po prostu być odpowiednio zsynchronizowane, co oznacza, że ​​zmodyfikujesz kod daty w górę (później) w nazwie pliku dla tabel, w których potrzebujesz kluczy obcych. Alternatywnie lub dodatkowo, obniż kod danych dla tabel, które nie potrzebują kluczy obcych.

Zaletą modyfikacji kodu danych jest to, że kod migracji będzie łatwiejszy do odczytania i utrzymania.

Do tej pory mój kod działa, dostosowując kod czasowy w celu wypychania migracji, które wymagają kluczy obcych.

Mam jednak setki tabel, więc na samym końcu mam ostatnią tabelę tylko dla kluczy obcych. Tylko po to, żeby wszystko płynęło. Zakładam, że wciągnę je do odpowiedniego pliku i zmodyfikuję kod danych podczas ich testowania.

Przykład: plik 2016_01_18_999999_create_product_options_table. Ten wymaga utworzenia tabeli produktów. Spójrz na nazwy plików.

 public function up()
{
    Schema::create('product_options', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('product_attribute_id')->unsigned()->index();
        $table->integer('product_id')->unsigned()->index();
        $table->string('value', 40)->default('');
        $table->timestamps();
        //$table->foreign('product_id')->references('id')->on('products');
        $table->foreign('product_attribute_id')->references('id')->on('product_attributes');
        $table->foreign('product_id')->references('id')->on('products');


    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('product_options');
}

tabela produktów: najpierw należy przeprowadzić migrację. 2015_01_18_000000_create_products_table

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');

        $table->string('style_number', 64)->default('');
        $table->string('title')->default('');
        $table->text('overview')->nullable();
        $table->text('description')->nullable();


        $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('products');
}

I w końcu na samym końcu plik, którego tymczasowo używam do rozwiązywania problemów, który zrefakturuję, pisząc testy dla modeli, które nazwałem 9999_99_99_999999_create_foreign_keys.php. Te klucze są komentowane, gdy je wyciągnąłem, ale rozumiesz.

    public function up()
    {
//        Schema::table('product_skus', function ($table) {
//            $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
//    });

    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
//        Schema::table('product_skus', function ($table)
//        {
//            $table->dropForeign('product_skus_product_id_foreign');
//        });
Iannazzi
źródło
2

Tak prosty !!!

jeśli 'priorities'tworzony jest pierwszy plik migracji, Laravel uruchamia się po raz pierwszy, 'priorities'gdy 'users'tabela nie istnieje.

jak może dodać relację do tabeli, która nie istnieje!

Rozwiązanie: wyciągnij kody kluczy obcych z 'priorities'tabeli. Twój plik migracji powinien wyglądać tak:

wprowadź opis zdjęcia tutaj

i dodaj do nowego pliku migracji, tutaj jest jego nazwa create_prioritiesForeignKey_tablei dodaj te kody:

public function up()
{        
    Schema::table('priorities', function (Blueprint $table) {          
        $table->foreign('user_id')
              ->references('id')
              ->on('users');                        
    });
}
Joseph
źródło
2

upewnij się, że twoja kolumna foreing jest zbyt szeroka

Mam na myśli, że twój klucz foreing (w drugiej tabeli) musi być tego samego typu, co twój klucz prognostyczny pontera (w pierwszej tabeli)

klucz główny wskaźnika musi być dodany bez znaku, pozwól mi pokazać:

w tabeli PIERWSZA migracja:

$table->increments('column_name'); //is INTEGER and UNSIGNED

w tabeli migracji DRUGIEJ:

$table->integer('column_forein_name')->unsigned(); //this must be INTEGER and UNSIGNED
$table->foreign('column_forein_name')->references('column_name')->on('first_table_name');

KOLEJNY PRZYKŁAD ZOBACZ RÓŻNICĘ

w tabeli PIERWSZA migracja:

$table->mediumIncrements('column_name'); //is MEDIUM-INTEGER and UNSIGNED

w tabeli migracji DRUGIEJ:

$table->mediumInteger('column_forein_name')->unsigned(); //this must be MEDIUM-INTEGER and UNSIGNED
$table->foreign('column_forein_name')->references('column_name')->on('first_table_name');

ZOBACZ MYSQL TYPY ZAKRESÓW TABELI

Rubén Ruíz
źródło
2

Zauważyłem jedną rzecz, że jeśli tabele używają innego silnika niż ograniczenie klucza obcego nie działa.

Na przykład, jeśli jedna tabela używa:

$table->engine = 'InnoDB';

I inne zastosowania

$table->engine = 'MyISAM';

wygeneruje błąd:

SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint

Możesz to naprawić, dodając InnoDB na końcu tworzenia tabeli w następujący sposób:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedInteger('business_unit_id')->nullable();

        $table->string('name', 100);

        $table->foreign('business_unit_id')
                ->references('id')
                ->on('business_units')
                ->onDelete('cascade');

        $table->timestamps();
        $table->softDeletes();
        $table->engine = 'InnoDB'; # <=== see this line
    });
}
erlandmuchasaj
źródło
1

W moim przypadku odwoływałem się do kolumny liczb całkowitych w id kolumnie ciągów znaków user_id . Zmieniłam:

$table->string('user_id')

do:

$table->integer('user_id')->unsigned();

Mam nadzieję, że to komuś pomaga!

Raphael Rafatpanah
źródło
1

Istotą jest to, że metoda obca używa ALTER_TABLEdo przekształcenia istniejącego pola w klucz obcy. Musisz więc zdefiniować typ tabeli przed zastosowaniem klucza obcego. Jednak nie musi to być osobne Schema::połączenie. Możesz zrobić oba w ramach tworzenia, jak poniżej:

public function up()
{
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

Należy również pamiętać, że typ user_idjest ustawiony na unsigned, aby dopasować klucz obcy.

Menasheh
źródło
1

Możesz bezpośrednio przekazać parametr boolowski w kolumnie liczb całkowitych, mówiąc, że powinien być bez znaku lub nie. W laravel 5.4 następujący kod rozwiązał mój problem.

        $table->integer('user_id', false, true);

W tym przypadku drugi parametr false oznacza, że ​​nie powinien on automatycznie zwiększać, a trzeci parametr true oznacza, że ​​powinien być niepodpisany. Możesz zachować ograniczenie klucza obcego podczas tej samej migracji lub oddzielić je. Działa na obu.

Mohit Satish Pawar
źródło
1

Jeśli żadne z powyższych rozwiązań nie działa dla początkujących, sprawdź, czy oba identyfikatory mają ten sam typ: oba są integerlub oba sąbigInteger , ... Możesz mieć coś takiego:

Główny stół (na przykład użytkownicy)

$table->bigIncrements('id');

Stolik dziecięcy (na przykład priorytety)

$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

To zapytanie nie powiodło się, ponieważ users.idjest BIG INTEGERnatomiast priorities.user_idto INTEGER.

Prawidłowe zapytanie w tym przypadku byłoby następujące:

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Waiyl Karim
źródło
1

W moim przypadku nie zadziałało, dopóki nie uruchomiłem polecenia

composer dump-autoload

w ten sposób możesz zostawić klucze obce wewnątrz schematu tworzenia

public function up()
{
    //
     Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
 }

 /**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}
Vladimir Salguero
źródło
1

Może to być również Twoja kolejność migracji tworzenia. Jeśli najpierw utworzysz tabelę priorytetów, a następnie tabelę użytkowników, będzie to nieprawidłowe. Z powodu pierwszej migracji poszukuję tabeli użytkowników. Musisz więc zmienić kolejność migracji

app/database/migrations

informator

Turan Zamanlı
źródło
1

Dla mnie kolumna tabeli, do której odwoływała się moja tabela potomna, nie była indeksowana.

Schema::create('schools', function (Blueprint $table) {
    $table->integer('dcid')->index()->unque();
    $table->integer('school_number')->index(); // The important thing is that this is indexed
    $table->string('name');
    $table->string('abbreviation');
    $table->integer('high_grade');
    $table->integer('low_grade');
    $table->timestamps();
    $table->primary('dcid');
});

Schema::create('students', function (Blueprint $table) {
      $table->increments('id');
      $table->integer('dcid')->index()->unique()->nullable();
      $table->unsignedInteger('student_number')->nullable();
      $table->integer('schoolid')->nullable();
      $table->foreign('schoolid')->references('school_number')->on('schools')->onDelete('set null');
      // ...
});

Zignoruj ​​straszne nazewnictwo, pochodzi z innego strasznie zaprojektowanego systemu.

Dotacja
źródło
1

Czasami ten błąd może wystąpić z powodu sekwencji migracji.

Podobnie jak Użytkownicy i Zamówienie to dwie tabele

Tabela zamówień ma klucz foriegn użytkowników (podczas migracji, jeśli migracja tabeli zamówień najpierw spowoduje problem, ponieważ nie ma użytkowników pasujących do klucza obcego)

Rozwiązanie: Wystarczy umieścić tabelę aktualizacji zamówienia pod użytkownikami w celu aktualizacji

Przykład: w moim przypadku tabele edukacji i uczelni Tabela edukacji

public function up()
{
    Schema::create('doc_education', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('uni_id')->unsigned()->nullable();
        $table->timestamps();
    });
}

Na Uniwersytecie

    Schema::create('doc_universties', function (Blueprint $table) {
        $table->increments('id');
        $table->string('uni_name');
        $table->string('location')->nullable();
        $table->timestamps();

        //
    });



Schema::table('doc_education', function(Blueprint $table) {
        $table->foreign('uni_id')->references('id')
        ->on('doc_universties')->onDelete('cascade');
    });
BlockCode
źródło
0

Jednej rzeczy, której moim zdaniem brakuje w odpowiedziach tutaj, i proszę mnie poprawić, jeśli się mylę, ale klucze obce muszą być indeksowane w tabeli przestawnej. Wydaje się, że tak jest przynajmniej w mysql.

public function up()
{
    Schema::create('image_post', function (Blueprint $table) {
        $table->engine = 'InnoDB';
        $table->increments('id');
        $table->integer('image_id')->unsigned()->index();
        $table->integer('post_id')->unsigned()->index();
        $table->timestamps();
    });

    Schema::table('image_post', function($table) {
        $table->foreign('image_id')->references('id')->on('image')->onDelete('cascade');
        $table->foreign('post_id')->references('id')->on('post')->onDelete('cascade');
    });

}
Ossi
źródło