Migrazione: impossibile aggiungere il vincolo di chiave esterna


207

Sto cercando di creare chiavi esterne in Laravel, tuttavia quando eseguo la migrazione della mia tabella utilizzando artisanmi viene visualizzato il seguente errore:

[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`))     

Il mio codice di migrazione è il seguente:

file di migrazione delle priorità

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

file di migrazione degli utenti

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

Qualche idea su cosa ho fatto di sbagliato, voglio ottenerlo in questo momento, poiché ho molte tabelle che devo creare, ad esempio Utenti, Clienti, Progetti, Attività, Stati, Priorità, Tipi, Squadre. Idealmente, voglio creare tabelle che contengono questi dati con le chiavi esterne, i..e clients_projected project_tasksecc.

Spero che qualcuno possa aiutarmi a iniziare.

Risposte:


357

Aggiungilo in due passaggi ed è bene anche renderlo non firmato:

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

}

117
Grazie Antonio! Per me il problema non è stato l'aggiunta di unsigned () nella colonna user_id in modo che corrispondesse al tipo di dati della colonna id sulla tabella degli utenti. La funzione incrementi ('id') di Laravel crea un numero intero senza segno, quindi anche la colonna chiave esterna deve essere senza segno.
Brad Griffith,

7
l'aggiunta di unsigned, oltre a separare il Schema::tablemetodo ha aiutato! Grazie!
patrickjason91,

4
Per me non è stato anche rendere l'ID non firmato. Grazie per il consiglio.
Carl Weis,

6
La soluzione è nel commento di @BradGriffith. Come notato sopra di me, non è necessario separarsi affatto. Forse è meglio aggiornare la risposta di conseguenza.
Matanya,

11
Utilizzare $table->unsignedBigInteger('user_id')se user.id èbigIncrements
Maksim Ivanov,

114

La domanda ha già risposto, ma spero che questo possa aiutare qualcun altro.

Questo errore si è verificato per me perché ho creato la tabella di migrazione con la chiave esterna in esso prima che la chiave esistesse come chiave primaria nella sua tabella originale. Le migrazioni vengono eseguite nell'ordine in cui sono state create come indicato dal nome del file generato dopo l'esecuzione migrate:make. Es 2014_05_10_165709_create_student_table.php.

La soluzione era quella di rinominare il file con la chiave esterna in un momento precedente rispetto al file con la chiave primaria come raccomandato qui: http://forumsarchive.laravel.io/viewtopic.php?id=10246

Penso di dover aggiungere anche $table->engine = 'InnoDB';


4
Dopo aver rinominato il file di migrazione e ottenere alcuni errori come: Impossibile aprire il flusso: nessun file o directory (e viene visualizzato il vecchio nome di migrazione) è necessario eseguire: compositore dump-autoload
Stelian

14
$ table-> engine = 'InnoDB'; è richiesto per imporre la chiave esterna a livello di MySql. Il motore laravel predefinito è MyIsam che non supporta le chiavi esterne!
François Breton,

2
questo ha funzionato anche per me, grazie. Ma mi sembra un po 'strano che funzioni in questo modo. Voglio dire, ha senso, ma dovrebbe esserci un modo per specificare l'ordine dell'esecuzione della migrazione oltre a rinominare manualmente i file e trovare date false nel processo
allisius

2
Sono venuto qui non perché stavo riscontrando errori, ma sono stato in grado di aggiungere valori errati alla colonna che era una chiave esterna. Poi ho visto il commento e la risposta su InnoDB. Questo era buono a sapersi. Grazie ragazzi :)
SuperNOVA il

2
L'ordine in cui sono state create le migrazioni rimane importante durante la migrazione. Ho riscontrato questo problema ma questo l'ha risolto.
Mugabit,

60

Laravel ^ 5.8

A partire da Laravel 5.8 , gli stub di migrazione utilizzano il metodo bigIncrements sulle colonne ID per impostazione predefinita. In precedenza, le colonne ID venivano create utilizzando il metodo degli incrementi.

Ciò non influirà su alcun codice esistente nel progetto; tuttavia, tenere presente che le colonne di chiave esterna devono essere dello stesso tipo . Pertanto, una colonna creata utilizzando il metodo degli incrementi non può fare riferimento a una colonna creata utilizzando il metodo bigIncrements.

Fonte: migrazioni e bigIncrements


Esempio

Immaginiamo di creare una semplice applicazione basata sui ruoli e che sia necessario fare riferimento a user_id nella tabella 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');
    });
}

Come puoi vedere, la riga commentata genererà un'eccezione di query, perché, come menzionato nelle note di aggiornamento, le colonne di chiave esterna devono essere dello stesso tipo , quindi è necessario modificare la chiave di inoltro (in questo esempio è user_id ) in bigInteger nella tabella role_user o modifica il metodo bigIncrements per incrementare il metodo nella tabella degli utenti e utilizzare la riga commentata nella tabella pivot, dipende da te.


Spero di essere stato in grado di chiarire questo problema.


1
Grazie. mi hai salvato la vita. Seguendo la tua spiegazione, ho cambiato la mia chiave esterna in bigInteger come mi hai suggerito. 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'); } Ha funzionato. Grazie.
Bruce Tong,

1
@BruceTong, sono contento di essere stato in grado di aiutarti.
chebaby,

1
Sì, questa è la risposta più pertinente.
Mohd Abdul Mujib,

1
Questa risposta è molto utile
Karim Pazoki,

1
Migliore risposta. Grazie
VishalParkash il

49

Nel mio caso, il problema era che la tabella principale conteneva già dei record e stavo forzando la nuova colonna a non essere NULL. Quindi aggiungere un -> nullable () alla nuova colonna ha fatto il trucco. Nell'esempio della domanda sarebbe qualcosa del genere:

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

o:

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

Spero che questo aiuti qualcuno!


Nota che anche la colonna 'id' nella tabella principale deve essere senza segno! Usando una linea come $ table-> increments ('id'); verrà automaticamente impostato su unsigned.
Colin Stadig,

Questo ha funzionato per me. Ho modificato il tipo di dati dell'ID tabella padre da BigIncrements a incrementi.
Emmanuel Benson,

22

Nel mio caso il problema era che l' usersimpostazione della migrazione generata automaticamente per la tabella

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

Quindi ho dovuto cambiare il tipo di colonna


$table->bigInteger('id');

per far funzionare la mia migrazione con la chiave esterna.

Questo con laravel 5.8.2


Perché la colonna chiave esterna deve avere lo stesso tipo di colonna a cui fa riferimento
Daniele

9
Questo ha funzionato per me $ table-> unsignedBigInteger ('user_id'); in laravel 5.8. *
Adam Winnipass

Ho avuto anche questo problema con 5.8, questo mi ha risolto! Grazie!
Mike Sheward,

Mi ha salvato da una lunga notte!
chq

19

Nel mio caso, il problema riguardava i tempi di migrazione, fare attenzione quando si creano migrazioni, in primo luogo creare la migrazione figlio rispetto alla migrazione di base. Perché se si crea prima la migrazione di base che ha la chiave esterna cercherà la tabella figlio e non ci sarà una tabella che quindi genera un'eccezione.

Inoltre:

Quando si crea la migrazione, ha un timestamp all'inizio di esso. supponiamo che tu abbia creato un gatto migratore in modo che assomigli 2015_08_19_075954_the_cats_time.phpe abbia questo codice

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

E dopo aver creato la tabella di base si crea un'altra razza di migrazione che è tabella figlio che ha il proprio timbro di data e ora di creazione. Il codice sarà simile a:

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

sembra che entrambe le tabelle siano corrette ma quando si esegue php artisan migrate . Genererà un'eccezione perché la migrazione creerà prima la tabella di base nel database perché è stata creata prima questa migrazione e la nostra tabella di base ha un vincolo di chiave esterna in essa che cercherà la tabella figlio e la tabella figlio non esiste che è probabilmente un'eccezione..

Così:

Creare prima la migrazione della tabella figlio.

Creare la migrazione della tabella di base dopo la creazione della migrazione figlio.

php artigiano migrare.

fatto funzionerà


13

Nel mio caso, ho appena cambiato l'ordine in cui le migrazioni vengono eseguite manualmente, in modo da creare prima gli utenti della tabella.

Nel database delle cartelle / migrazioni / il nome del file di migrazione ha questo formato: year_month_day_hhmmss_create_XXXX_table.php

Basta rinominare creare il file utente in modo che la data di creazione della tabella delle priorità della tabella sia impostata dopo la data dell'utente (è sufficiente anche un secondo dopo)


13

In laravel 5.8, users_table utilizza il bigIncrements('id')tipo di dati per la chiave primaria. Pertanto, quando si desidera fare riferimento a un vincolo di chiave esterna, è necessario digitare la user_idcolonna unsignedBigInteger('user_id').


grazie mille, ho passato un'ora a cercare di capire perché la chiave esterna sta causando l'eccezione
Ya Basha,

10

Stavo riscontrando lo stesso problema con Laravel 5.8. Dopo aver dato un'occhiata più da vicino ai documenti laravel, inoltre qui Migrations & bigIncrements . Il modo in cui l'ho risolto è aggiungendo le chiavi primarie "$ table-> bigIncrements ('id')" a ogni singola tabella correlata alla tabella "utenti" e alle sue associazioni, nel mio caso la tabella "ruolo" . Infine, ho avuto "$ table-> unsignedBigInteger" per associare i ruoli agli utenti (Many-to-Many), ovvero la tabella "role_user" .

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

9

Ho avuto questo problema con laravel 5.8 e ho risolto questo codice, come mostrato qui nella documentazione di Laravel , dove mai aggiungerò una chiave esterna.

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

poi ho corso $ php artisan migrate:refresh

Poiché questa sintassi è piuttosto dettagliata, Laravel fornisce metodi più terser che utilizzano la convenzione per fornire un'esperienza di sviluppo migliore. L'esempio sopra potrebbe essere scritto così:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
});

7

L'uso di Laravel 5.3 ha avuto lo stesso problema.

La soluzione consisteva nell'utilizzare unsignedInteger anziché integer ('name') -> unsigned () .

Quindi questo è ciò che ha funzionato

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

Il motivo per cui ha funzionato è il fatto che quando si utilizza integer ('name') -> unsigned la colonna creata nella tabella aveva lunghezza 11, ma quando si utilizza unsigedInteger ('name') la colonna aveva lunghezza 10.

Lunghezza 10 è la lunghezza delle chiavi primarie quando si utilizza Laravel in modo che la lunghezza delle colonne corrisponda.


Amico, grazie per quello che stavo per mollare e gestire il sql grezzo appena ho trovato il tuo post. Dovrò leggere di più sul motivo per cui la chiave primaria laravel deve essere di lunghezza 10 e se c'è qualche motivo per cui fare integer ('colonna') -> unsigned () dovrebbe essere diverso da unsigedInteger ('colonna')
Arnaud Bouchot

6

Questo errore si è verificato per me perché - mentre la tabella che stavo provando a creare era InnoDB - la tabella esterna a cui stavo cercando di metterlo in relazione era una tabella MyISAM!


MyISAM non supporta i vincoli di chiave esterna. Probabilmente ha funzionato perché il passaggio a MyISAM ha fatto sì che ignorasse completamente la chiave esterna che probabilmente era lì per un motivo. Stai attento.
greggle138,

5

Non è possibile aggiungere relazioni, a meno che non vengano create tabelle correlate. Laravel esegue le migrazioni in ordine di data dei file di migrazione. Pertanto, se si desidera creare una relazione con una tabella esistente nel secondo file di migrazione, non riesce.

Ho riscontrato lo stesso problema, quindi ho creato un altro file di migrazione per specificare tutte le relazioni.

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

1
come hai chiamato il file? 9999_99_99_999999_create_foreign_keys.php?
Iannazzi,

l'aggiunta di 9999_99_99_99999 al nome del file di migrazione non è una buona idea in quanto rovinerà la funzione di rollback.
Maulik Gangani,

5

Attenzione: quando Laravel imposta un tavolo usando

$table->increments('id');

che è standard nella maggior parte delle migrazioni, imposterà un campo intero senza segno. Pertanto, quando si effettua un riferimento esterno da un'altra tabella a questo campo, assicurarsi che nella tabella di riferimento, si imposti il ​​campo su UnsignedInteger e non (quello che avrei assunto essere un) campo UnsignedBigInteger.

Ad esempio: nel file di migrazione 2018_12_12_123456_create_users_table.php:

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

Quindi nel file di migrazione 2018_12_12_18000000_create_permissions_table.php, che imposta il riferimento esterno agli utenti:

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

5

Dovresti scrivere in questo modo

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

Il campo chiave esterna dovrebbe essere senza segno , spero che sia d'aiuto !!


Non solo unsigned ma quando fa riferimento a una colonna bigIncrements, dovrebbe essere unsigedBigInteger
gondwe

4

Per aver aggiunto il vincolo di chiave esterna in laravel, per me ha funzionato:

  1. Creare la colonna come chiave esterna come segue:

    $ Tavola-> intero ( 'column_name') -> unsigned ();
  2. Aggiunta della linea di vincolo immediatamente dopo (1), ad es

    $ Tavola-> intero ( 'column_name') -> unsigned ();
    $ Tavola-> estera ( 'column_name') -> i riferimenti ( 'pk_of_other_table') -> on ( 'other_table');

3

so che è una vecchia domanda, ma assicurati che se stai lavorando con riferimenti è definito il motore di supporto adeguato. imposta il motore innodb per entrambe le tabelle e lo stesso tipo di dati per le colonne di riferimento

$table->engine = 'InnoDB';

2

Risentendo qui alcuni anni dopo la domanda originale, usando laravel 5.1, ho avuto lo stesso errore delle mie migrazioni generate al computer con lo stesso codice data. Ho esaminato tutte le soluzioni proposte, quindi ho eseguito il refactoring per trovare la fonte dell'errore.

Nelle seguenti laracast e nella lettura di questi post, credo che la risposta corretta sia simile alla risposta di Vickies, con l'eccezione che non è necessario aggiungere una chiamata di schema separata. Non è necessario impostare la tabella su Innodb, suppongo che Laravel lo stia facendo.

Le migrazioni devono semplicemente essere cronometrate correttamente, il che significa che modificherai il codice data (più tardi) nel nome file per le tabelle su cui hai bisogno di chiavi esterne. In alternativa o in aggiunta, abbassa il codice dati per le tabelle che non richiedono chiavi esterne.

Il vantaggio nella modifica del codice dati è che il codice di migrazione sarà più facile da leggere e gestire.

Finora il mio codice funziona regolando il time code in alto per respingere le migrazioni che richiedono chiavi esterne.

Tuttavia, ho centinaia di tabelle, quindi alla fine ho un'ultima tabella solo per le chiavi esterne. Solo per far fluire le cose. Suppongo che li inserirò nel file corretto e modificherò il codice dati mentre li collaudo.

Quindi un esempio: file 2016_01_18_999999_create_product_options_table. Questo richiede la creazione della tabella dei prodotti. Guarda i nomi dei file.

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

la tabella dei prodotti: questo deve prima migrare. 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');
}

E infine alla fine il file che sto temporaneamente usando per risolvere i problemi, che rifatterò mentre scrivo i test per i modelli che ho chiamato 9999_99_99_999999_create_foreign_keys.php. Questi tasti sono commentati quando li ho estratti, ma ottieni il punto.

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

2

Così semplice !!!

se il tuo primo 'priorities'file di migrazione viene creato, Laravel viene eseguito per la prima volta 'priorities'mentre la 'users'tabella non esiste.

come può aggiungere una relazione a una tabella che non esiste !.

Soluzione: estrarre i codici di chiave esterna dalla 'priorities'tabella. il tuo file di migrazione dovrebbe essere così:

inserisci qui la descrizione dell'immagine

e aggiungi a un nuovo file di migrazione, qui il suo nome è create_prioritiesForeignKey_tablee aggiungi questi codici:

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

2

assicurati che la tua colonna anteriore sia di gran moda per la colonna chiave anteriore

Voglio dire che il tuo Foreingkey (nella seconda tabella) deve essere lo stesso tipo della tua chiave iniziale ponter (nella prima tabella)

la chiave principale del puntatore deve essere un metodo senza segno, fammi mostrare:

sulla tua PRIMA tabella di migrazione:

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

sulla tua seconda tabella di migrazione:

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

UN ALTRO ESEMPIO PER VEDERE LA DIFFERENZA

sulla tua PRIMA tabella di migrazione:

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

sulla tua seconda tabella di migrazione:

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

VEDI GAMMA DI TABELLA DEI TIPI NUMERICI DI MYSQL


2

Una cosa che ho notato è che se le tabelle utilizzano un motore diverso rispetto al vincolo di chiave esterna non funziona.

Ad esempio se una tabella utilizza:

$table->engine = 'InnoDB';

E l'altro usa

$table->engine = 'MyISAM';

genererebbe un errore:

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

Puoi risolvere questo problema semplicemente aggiungendo InnoDB alla fine della creazione della tabella in questo modo:

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

1

Nel mio caso, stavo facendo riferimento a una colonna intera id su una colonna stringa user_id . Ho cambiato:

$table->string('user_id')

per:

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

Spero che aiuti qualcuno!


1

L'essenza è che il metodo esterno utilizza ALTER_TABLEper trasformare un campo preesistente in una chiave esterna. Quindi devi definire il tipo di tabella prima di applicare la chiave esterna. Tuttavia, non deve essere in una Schema::chiamata separata . Puoi fare entrambi all'interno di create, in questo modo:

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

Si noti inoltre che il tipo di user_idè impostato su unsigned per corrispondere alla chiave esterna.


1

Puoi passare direttamente il parametro booleano nella colonna intera dicendo che dovrebbe essere senza segno o meno. In laravel 5.4 il seguente codice ha risolto il mio problema.

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

Qui il secondo parametro false indica che non deve essere auto-incrementante e il terzo parametro true indica che deve essere senza segno. È possibile mantenere il vincolo di chiave esterna nella stessa migrazione o separarlo. Funziona su entrambi.


1

Se nessuna delle soluzioni precedenti funziona per i neofiti, controlla se entrambi gli ID hanno lo stesso tipo: entrambi sono integero entrambi lo sono bigInteger, ... Puoi avere qualcosa del genere:

Tabella principale (utenti ad esempio)

$table->bigIncrements('id');

Tabella figlio (priorità ad esempio)

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

Questa query fallirà perché users.idè un BIG INTEGERconsiderando priorities.user_idè un INTEGER.

La query corretta in questo caso sarebbe la seguente:

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

1

Nel mio caso non ha funzionato fino a quando non ho eseguito il comando

composer dump-autoload

in questo modo è possibile lasciare le chiavi esterne all'interno dello schema di creazione

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

1

Potrebbe anche essere il tuo ordine di migrazione della creazione. Se prima crei una tabella delle priorità e dopo la tabella degli utenti, allora sarà sbagliato. A causa della prima migrazione alla ricerca della tabella degli utenti. Quindi, è necessario modificare l'ordinamento della migrazione su

app/database/migrations

elenco


1

Per me, la colonna della tabella a cui faceva riferimento la mia tabella figlio non era indicizzata.

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');
      // ...
});

Ignora la terribile denominazione, proviene da un altro sistema terribilmente progettato.


1

Alcune volte questo errore può verificarsi a causa della sequenza delle migrazioni.

Come gli utenti e l'ordine sono due tabelle

La tabella degli ordini ha una chiave degli utenti foriegn (durante la migrazione se la tabella degli ordini viene migrata per prima, il problema è causato dal fatto che non ci sono utenti che corrispondono alla chiave esterna)

Soluzione: basta mettere la tabella di aggiornamento dell'ordine sotto gli utenti per l'aggiornamento

Esempio: nel mio caso Tabelle di istruzione e università Tabella di istruzione

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

Nell'università

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

0

Una cosa che ritengo manchi dalle risposte qui, e per favore correggimi se sbaglio, ma le chiavi esterne devono essere indicizzate nella tabella pivot. Almeno in mysql questo sembra essere il caso.

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

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.