Migración: no se puede agregar la restricción de clave externa

207

Sin embargo, estoy tratando de crear claves foráneas en Laravel cuando migro mi tabla usando artisan aparece el siguiente error:

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

Mi código de migración es así:

archivo de migración de prioridades

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

archivo de migración de usuarios

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

Cualquier idea sobre lo que he hecho mal, quiero obtener esto ahora, ya que tengo muchas tablas que necesito crear, por ejemplo, usuarios, clientes, proyectos, tareas, estados, prioridades, tipos, equipos. Idealmente, quiero crear tablas que contengan estos datos con las claves externas, es decir, clients_projecteproject_tasks etc.

Espero que alguien pueda ayudarme a comenzar.

001221
fuente

Respuestas:

357

Agréguelo en dos pasos, y también es bueno hacerlo sin firmar:

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
fuente
117
Gracias Antonio! Para mí, el problema no era agregar unsigned () en la columna user_id para que coincidiera con el tipo de datos de la columna id en la tabla de usuarios. La función de incrementos de Laravel ('id') crea un entero sin signo, por lo que la columna de clave externa también debe estar sin signo.
Brad Griffith
77
agregar sin firmar, aparte de separar al Schema::tablemétodo ¡ayudó! ¡Gracias!
patrickjason91
44
Para mí, no estaba haciendo que la identificación no estuviera firmada también. Gracias por el consejo.
Carl Weis
66
La solución está en el comentario de @BradGriffith. Como se señaló anteriormente, no hay necesidad de separarse en absoluto. Quizás sea mejor actualizar la respuesta en consecuencia.
Matanya
11
Úselo $table->unsignedBigInteger('user_id')si su user.id esbigIncrements
Maksim Ivanov
114

Pregunta ya respondida, pero espero que esto pueda ayudar a alguien más.

Este error se produjo para mí porque creé la tabla de migración con la clave externa en primer lugar antes de que la clave existiera como clave principal en su tabla original. Las migraciones se ejecutan en el orden en que fueron creadas, como lo indica el nombre del archivo generado después de ejecutarse migrate:make. Por ej 2014_05_10_165709_create_student_table.php.

La solución fue cambiar el nombre del archivo con la clave externa a un tiempo anterior al archivo con la clave primaria como se recomienda aquí: http://forumsarchive.laravel.io/viewtopic.php?id=10246

Creo que también tuve que agregar $table->engine = 'InnoDB';

haakym
fuente
44
Después de cambiar el nombre del archivo de migración y obtener algunos errores como: Error al abrir la secuencia: no existe dicho archivo o directorio (y se muestra el nombre de migración anterior) debe ejecutar: composer dump-autoload
Stelian
14
$ tabla-> motor = 'InnoDB'; se requiere para aplicar la clave externa a nivel de MySql. ¡El motor laravel predeterminado es MyIsam que no admite claves foráneas!
François Breton
2
Esto también funcionó para mí, gracias. Pero me parece un poco extraño que funcione de esta manera. Quiero decir, tiene sentido, pero debería haber una forma de especificar el orden de la ejecución de la migración que no sea renombrar manualmente los archivos y obtener fechas falsas en el proceso
allisius
2
Vine aquí no porque recibiera ningún error, sino que pude agregar valores incorrectos a la columna, que era una clave foránea. Entonces vi el comentario y la respuesta sobre InnoDB. Esto fue bueno saberlo. Gracias chicos :)
SuperNOVA
2
El orden en el que creó sus migraciones sigue siendo importante al migrar. Me encontré con este problema, pero esto lo resolvió.
mugabits
60

Laravel ^ 5.8

A partir de Laravel 5.8 , los apéndices de migración utilizan el método bigIncrements en las columnas de ID de forma predeterminada. Anteriormente, las columnas de ID se creaban utilizando el método de incrementos.

Esto no afectará ningún código existente en su proyecto; sin embargo, tenga en cuenta que las columnas de clave externa deben ser del mismo tipo . Por lo tanto, una columna creada con el método de incrementos no puede hacer referencia a una columna creada con el método bigIncrements.

Fuente: Migraciones y bigIncrements


Ejemplo

Imaginemos que está creando una aplicación simple basada en roles y necesita hacer referencia a user_id en la tabla 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');
    });
}

Como puede ver, la línea comentada arrojará una excepción de consulta, porque, como se menciona en las notas de actualización, las columnas de clave externa deben ser del mismo tipo , por lo tanto, debe cambiar la clave anterior (en este ejemplo es user_id ) a bigInteger en la tabla role_user o cambie el método bigIncrements a incrementos en la tabla de usuarios y use la línea comentada en la tabla dinámica, depende de usted.


Espero haber podido aclararles este problema.

chebaby
fuente
1
Gracias. me salvaste la vida. Siguiendo su explicación, cambié mi clave foránea a bigInteger como usted sugirió. 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'); } Funcionó. Gracias.
Bruce Tong
1
@BruceTong, me alegra haber podido ayudar.
chebaby
1
Sí, esta es la respuesta más relevante.
Mohd Abdul Mujib
1
Esta respuesta es muy útil.
Karim Pazoki
1
La mejor respuesta. Gracias
VishalParkash
49

En mi caso, el problema era que la tabla principal ya tenía registros y estaba obligando a la nueva columna a no ser NULL. Por lo tanto, agregar un -> nullable () a la nueva columna hizo el truco. En el ejemplo de la pregunta sería algo como esto:

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

o:

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

Espero que esto ayude a alguien!

AdrianCR
fuente
Tenga en cuenta que la columna 'id' en su tabla principal también debe estar sin firmar. Usando una línea como $ table-> increments ('id'); cambiará automáticamente a sin firmar.
Colin Stadig
Esto funcionó para mí. Cambié el tipo de datos del ID de la tabla principal de BigIncrements a incrementos.
Emmanuel Benson el
22

En mi caso, el problema era que la migración autogenerada para la userstabla estaba configurando

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

Entonces tuve que cambiar el tipo de columna


$table->bigInteger('id');

hacer que mi migración con la clave externa funcione.

Esto con laravel 5.8.2

Daniele
fuente
Debido a que la columna de clave externa debe tener el mismo tipo de columna a la que se refiere
Daniele
9
Esto funcionó para mí $ table-> unsignedBigInteger ('user_id'); en laravel 5.8. *
Adam Winnipass
También tuve este problema con 5.8, ¡esto me lo solucionó! ¡Gracias!
Mike Sheward
Me salvó de una larga noche!
chq
19

En mi caso, el problema fue con el tiempo de migración, tenga cuidado al crear migraciones, primero cree la migración secundaria que la migración base. Porque si crea primero la migración base que tiene su clave externa, buscará una tabla secundaria y no habrá una tabla que luego arroje una excepción.

Además:

Cuando crea la migración, tiene una marca de tiempo al comienzo. supongamos que ha creado un gato de migración para que se vea 2015_08_19_075954_the_cats_time.phpy tenga este código

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

Y después de crear la tabla base, crea otra raza de migración , que es la tabla secundaria, tiene su propio sello de fecha y hora de creación. El código se verá así:

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

parece que ambas tablas son correctas, pero cuando ejecuta php artisan migrate . Lanzará una excepción porque la migración primero creará la tabla base en su base de datos porque usted ha creado esta migración primero y nuestra tabla base tiene una restricción de clave externa que buscará la tabla secundaria y la tabla secundaria no existe, lo que probablemente sea una excepción..

Entonces:

Cree primero la migración de la tabla secundaria.

Cree la migración de la tabla base después de crear la migración secundaria.

PHP artesanal migrar.

hecho funcionará

Vicky
fuente
13

En mi caso, solo cambio el orden en que las migraciones se ejecutan manualmente para que los usuarios de la tabla se creen primero.

En la base de datos de carpetas / migraciones / su nombre de archivo de migración tiene este formato: year_month_day_hhmmss_create_XXXX_table.php

Simplemente cambie el nombre de crear archivo de usuario para que la fecha de creación de la tabla de prioridades de la tabla se establezca después de la fecha del usuario (incluso un segundo más tarde es suficiente)

ldt
fuente
13

En laravel 5.8, users_table usa bigIncrements('id')el tipo de datos para la clave primaria. De modo que cuando desee hacer referencia a una restricción de clave externa, su user_idcolumna debe ser de unsignedBigInteger('user_id')tipo.

Dhara Talaviya
fuente
muchas gracias, pasé una hora tratando de descubrir por qué la clave foránea está causando la excepción
Ya Basha
10

Estaba teniendo el mismo problema al usar Laravel 5.8. Después de echar un vistazo más de cerca a laravel docs, además, aquí Migraciones y bigIncrements . La forma en que lo resolví es agregando claves primarias "$ table-> bigIncrements ('id')" a cada tabla que está relacionada con la tabla "usuarios" y sus asociaciones, en mi caso la tabla "rol" . Por último, tenía "$ table-> unsignedBigInteger" para asociar roles a los usuarios (muchos a muchos), es decir, la tabla "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']);
        });
Capfer
fuente
9

Tuve este problema con laravel 5.8 y arreglé este código, como se muestra aquí en la documentación de Laravel , donde estoy agregando una clave foránea.

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

entonces corrí $ php artisan migrate:refresh

Dado que esta sintaxis es bastante detallada, Laravel proporciona métodos adicionales y terser que utilizan la convención para proporcionar una mejor experiencia de desarrollador. El ejemplo anterior podría escribirse así:

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

Usar Laravel 5.3 tuvo el mismo problema.

La solución fue usar unsignedInteger en lugar de entero ('nombre') -> unsigned () .

Entonces esto es lo que funcionó

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

La razón por la que esto funcionó es el hecho de que al usar entero ('nombre') -> sin firmar la columna creada en la tabla tenía una longitud de 11, pero cuando se usaba unsigedInteger ('nombre') la columna tenía una longitud de 10.

La longitud 10 es la longitud de las claves primarias cuando se usa Laravel, por lo que la longitud de las columnas coincide.

Radu Diță
fuente
Hombre, gracias por eso estaba a punto de rendirme y ejecutar el sql sin procesar cuando acabo de encontrar tu publicación. Tendré que leer más sobre por qué se obliga a la clave primaria laravel a ser de longitud 10 y si hay alguna razón por la que hacer entero ('columna') -> unsigned () debería ser diferente de unsigedInteger ('columna')
Arnaud Bouchot
6

Este error ocurrió porque, mientras que la tabla que intentaba crear era InnoDB, ¡la tabla externa con la que intentaba relacionarla era una tabla MyISAM!

baba
fuente
MyISAM no admite restricciones de clave externa. Probablemente funcionó porque cambiar a MyISAM hizo que ignorara por completo la clave externa que probablemente estaba allí por alguna razón. Ten cuidado.
greggle138
5

No podemos agregar relaciones, a menos que se creen tablas relacionadas. Laravel ejecuta las migraciones ordenadas por fecha de archivos de migración. Entonces, si desea crear una relación con una tabla que existe en el segundo archivo de migración, falla.

Enfrenté el mismo problema, así que creé un archivo de migración más por fin para especificar todas las relaciones.

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
fuente
1
¿Cómo llamaste el archivo? 9999_99_99_999999_create_foreign_keys.php?
Iannazzi
agregar 9999_99_99_99999 al nombre de archivo de migración es una mala idea, ya que arruinará la función de reversión.
Maulik Gangani
5

Tenga en cuenta: cuando Laravel configura una tabla usando

$table->increments('id');

que es estándar en la mayoría de las migraciones, esto configurará un campo entero sin signo. Por lo tanto, al hacer una referencia externa de otra tabla a este campo, asegúrese de que en la tabla de referencia, establezca el campo en UnsignedInteger y no (lo que supuse que era) campo UnsignedBigInteger.

Por ejemplo: en el archivo de migración 2018_12_12_123456_create_users_table.php:

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

Luego, en el archivo de migración 2018_12_12_18000000_create_permissions_table.php, que configura la referencia externa a los usuarios:

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
fuente
5

Deberías escribir de esta manera

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

El campo de clave externa no debe estar firmado , ¡espero que ayude!

Mahesh Yadav
fuente
No sólo sin firmar pero cuando se hace referencia a una columna bigIncrements, debe ser unsigedBigInteger
Gondwe
4

Para agregar la restricción de clave externa en laravel, lo siguiente funcionó para mí:

  1. Cree la columna para que sea clave externa de la siguiente manera:

    $ tabla-> entero ('nombre_columna') -> unsigned ();
  2. Agregar la línea de restricción inmediatamente después de (1) es decir

    $ tabla-> entero ('nombre_columna') -> unsigned ();
    $ table-> foreign ('column_name') -> referencias ('pk_of_other_table') -> on ('other_table');
bmnepali
fuente
3

Sé que es una pregunta antigua, pero asegúrese de que si está trabajando con referencias, se defina el motor de soporte adecuado. configura el motor innodb para ambas tablas y el mismo tipo de datos para las columnas de referencia

$table->engine = 'InnoDB';
di3
fuente
2

Entrando aquí unos años después de la pregunta original, usando laravel 5.1, tuve el mismo error ya que mis migraciones fueron generadas por computadora con el mismo código de fecha. Revisé todas las soluciones propuestas, luego refactoré para encontrar la fuente del error.

En las siguientes transmisiones, y al leer estas publicaciones, creo que la respuesta correcta es similar a la respuesta de Vickies, con la excepción de que no es necesario agregar una llamada de esquema por separado. No necesita poner la mesa en Innodb, supongo que ahora Laravel lo está haciendo.

Las migraciones simplemente deben programarse correctamente, lo que significa que modificará el código de fecha (más adelante) en el nombre del archivo para las tablas en las que necesita claves foráneas. Alternativamente o además, baje el código de fecha para las tablas que no necesitan claves foráneas.

La ventaja de modificar el código de fecha es que su código de migración será más fácil de leer y mantener.

Hasta ahora, mi código funciona ajustando el código de tiempo para retrasar las migraciones que necesitan claves externas.

Sin embargo, tengo cientos de tablas, así que al final tengo una última tabla solo para claves foráneas. Solo para que las cosas fluyan. Supongo que los pondré en el archivo correcto y modificaré el código de fecha mientras los pruebo.

Entonces, un ejemplo: archivo 2016_01_18_999999_create_product_options_table. Este necesita que se cree la tabla de productos. Mira los nombres de los archivos.

 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 tabla de productos: esto debe migrar primero. 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');
}

Y finalmente, al final, el archivo que estoy usando temporalmente para resolver problemas, que refactorizaré a medida que escriba pruebas para los modelos que denominé 9999_99_99_999999_create_foreign_keys.php. Estas claves se comentan cuando las saqué, pero entiendes el 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');
//        });
Iannazzi
fuente
2

Tan sencillo !!!

si crea su primer 'priorities'archivo de migración, Laravel se ejecuta por primera vez 'priorities'mientras la 'users'tabla no existe.

¡Cómo puede agregar una relación a una tabla que no existe !.

Solución: extraiga los códigos de clave externa de la 'priorities'tabla. su archivo de migración debería ser así:

ingrese la descripción de la imagen aquí

y agregue a un nuevo archivo de migración, aquí está su nombre create_prioritiesForeignKey_tabley agregue estos códigos:

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

asegúrese de que su columna externa esté muy extendida de la columna clave principal

Me refiero a que su clave anterior (en la segunda tabla) debe ser del mismo tipo que su clave principal ponter (en la primera tabla)

la clave principal de su puntero debe agregar un método sin signo, déjeme mostrarle:

en su PRIMERA tabla de migración:

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

en su SEGUNDA tabla de migración:

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

OTRO EJEMPLO PARA VER LA DIFERENCIA

en su PRIMERA tabla de migración:

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

en su SEGUNDA tabla de migración:

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

VER TABLAS DE TABLAS DE TIPOS NUMÉRICOS MYSQL

Rubén Ruíz
fuente
2

Una cosa que he notado es que si las tablas usan un motor diferente que la restricción de clave externa no funciona.

Por ejemplo, si una tabla usa:

$table->engine = 'InnoDB';

Y los otros usos

$table->engine = 'MyISAM';

generaría un error:

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

Puede solucionar esto simplemente agregando InnoDB al final de la creación de su tabla de la siguiente manera:

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
fuente
1

En mi caso, hacía referencia a una columna entera id en una columna de cadena user_id . Cambié:

$table->string('user_id')

a:

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

Espero que ayude a alguien!

Raphael Rafatpanah
fuente
1

La esencia es que el método externo se utiliza ALTER_TABLEpara convertir un campo preexistente en una clave externa. Por lo tanto, debe definir el tipo de tabla antes de aplicar la clave externa. Sin embargo, no tiene que estar en una Schema::llamada separada . Puedes hacer ambas cosas dentro de crear, así:

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

También tenga en cuenta que el tipo de user_idse establece en unsigned para que coincida con la clave externa.

Menasheh
fuente
1

Puede pasar directamente el parámetro booleano en la columna entera diciendo que debe estar sin signo o no. En laravel 5.4 el siguiente código resolvió mi problema.

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

Aquí, el segundo parámetro falso representa que no debe incrementarse automáticamente y el tercer parámetro verdadero representa que no debe estar firmado. Puede mantener la restricción de clave externa en la misma migración o separarla. Funciona en ambos.

Mohit Satish Pawar
fuente
1

Si ninguna de las soluciones anteriores funciona para los novatos, verifique si ambas ID tienen el mismo tipo: ambas son integero ambas son bigInteger, ... Puede tener algo como esto:

Tabla principal (usuarios por ejemplo)

$table->bigIncrements('id');

Tabla secundaria (prioridades, por ejemplo)

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

Esta consulta fallará porque users.ides un BIG INTEGERmientras que priorities.user_ides un INTEGER.

La consulta correcta en este caso sería la siguiente:

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

En mi caso no funcionó hasta que ejecuté el comando

composer dump-autoload

de esa manera puede dejar las claves foráneas dentro del esquema de creación

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
fuente
1

También puede ser su orden de migración de creación. Si primero crea una tabla de prioridades, y después de la tabla de usuarios, entonces será incorrecto. Debido a la primera migración buscando la tabla de usuarios. Por lo tanto, debe cambiar el orden de la migración en

app/database/migrations

directorio

Turan Zamanlı
fuente
1

Para mí, la columna de la tabla a la que hacía referencia mi tabla secundaria no estaba indexada.

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 el terrible nombre, es de otro sistema terriblemente diseñado.

Conceder
fuente
1

Algunas veces este error puede deberse a una secuencia de migraciones.

Usuarios similares y Orden son dos tablas

La tabla de pedidos tiene una clave extranjera de usuarios (durante la migración, si la tabla de pedidos migra primero, causará el problema porque no hay usuarios que coincidan con la clave externa)

Solución: solo coloque la tabla de actualización de pedidos debajo de los usuarios para actualizar

Ejemplo: en mi caso Tablas de educación y universidad Tabla de educación

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

En la Universidad

    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
fuente
0

Una cosa que creo que falta en las respuestas aquí, y corríjame si estoy equivocado, pero las claves foráneas deben indexarse ​​en la tabla dinámica. Al menos en mysql ese parece ser el 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');
    });

}
Ossi
fuente