web-dev-qa-db-fra.com

Laravel migration (errno: 150 "La contrainte de clé étrangère est mal formée")

J'ai une table d'ordres et un code sell_shipping_labels qui référence orders.id en tant qu'étranger. Cependant, lorsque je lance la migration Laravel, je reçois le code d'erreur redouté:

[Illuminate\Database\QueryException]
SQLSTATE [HY000]: Erreur générale: 1005 Impossible de créer la table cheapbooks_test.#sql-b5b_b2a (errno: 150 "La contrainte de clé étrangère n'est pas formée correctement") (SQL: modifiez la table sell_shipping_labels ajoutez une contrainte sell_shipping_labels_order_id_foreign clé étrangère (order_id) référence orders (id)) 

[Doctrine\DBAL\Driver\PDOException]
SQLSTATE [HY000]: Erreur générale: 1005 Impossible de créer la table cheapbooks_test.#sql-b5b_b2a (errno: 150 "La contrainte de clé étrangère est mal formée") 

Ceci est mon schéma de table orders:

   Schema::create('orders', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id');
        $table->integer('book_id');
        $table->integer('status_id');
        $table->double('payment_amount')->nullable();
        $table->timestamp('received_at')->nullable();
        $table->timestamp('paid_at')->nullable();
        $table->timestamps();
        $table->softDeletes();
    });

Et voici mon schéma sell_shipping_labels:

Schema::create('sell_shipping_labels', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedInteger('order_id');
        $table->string('shippo_object_id');
        $table->string('label_url');
        $table->string('tracking_url');
        $table->string('tracking_number');
        $table->timestamp('arrived_at');
        $table->timestamps();
        $table->softDeletes();

        $table->foreign('order_id')->references('id')->on('orders');
    });
}

Maintenant, j'ai retourné Internet à l'envers pour essayer de comprendre le problème. Tous les articles sur ce problème se réfèrent tous au fait que la table des commandes doit être crééeAVANTla table contenant la clé étrangère, mais ce n'est pas un problème pour moi car mes fichiers sont dans la bon ordre.

3
FrenchMajesty

Puisque increments() crée une colonne d’entier non signée, vous devez également définir la colonne de clé étrangère en tant qu’entier non signé:

$table->unsignedInteger('order_id');

Ou:

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

https://laravel.com/docs/5.5/migrations#foreign-key-constraints

10
Alexey Mezenin

Vérifiez l'ordre de vos migrations. Si votre commande migrate tente de créer la table sell_shipping_labels avant la table orders, cela se produira avec MySQL. Il semble continuer à créer une date de migration, du plus ancien au plus récent. En d'autres termes, le order_id sur la table qu'il tente de référencer doit exister.

J'ai rencontré le même problème et je change de date de migration.

1
Abid Shah

J'avais aussi la même erreur. Ce que je faisais dans utilisateurs table est,

$table->unsignedInteger('role_id')->default(2); table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');

Mais j'ai créé la table de rôle après avoir créé la table d'utilisateurs. J'ai donc modifié la date du nom du fichier de migration du rôle avant la date du fichier filename de la table users. Comme ça,

2013_01_22_091213_create_roles_table.php
2014_10_12_000000_create_users_table.php

Et finalement ça marche. Peut-être que parfois vous aurez ce problème. Donc, je l'ai posté.

0
Anand Mainali
  1. Les fichiers de migration doivent être créés de manière à ce que la migration parente soit la première, puis le fichier de migration avec la clé étrangère ensuite.
  2. La clé étrangère et l'identifiant principal dans l'autre table doivent avoir une propriété exactement similaire. Si l'identifiant principal est incrémenté, indiquez alors la clé étrangère sous la forme d'un entier ('xxx_id') -> unsigned ();
0
Ayenew Yihune

J'ai eu le même problème et résolu le problème en définissant le type de base de données sur innoDB

Les tables créées avant la migration où 'MyISAM à partir d'un système hérité et le fichier migré sont innoDB par défaut, le mélange de types de table était donc un problème dans mon cas.

0
alker

Pour ceux qui ont marqué la réponse n'a pas fonctionné:

Vérifiez le moteur de vos tables. Dans mon cas, je faisais référence à une table MyISAM dans une table InnoDB source. Après avoir changé le moteur de la table de référence en InnoDB, cela a fonctionné!

0
Erfun