web-dev-qa-db-fra.com

Suppression d'une colonne avec une clé étrangère Laravel erreur: erreur générale: 1025 Erreur lors du changement de nom

J'ai créé une table en utilisant la migration comme ceci:

public function up()
{
    Schema::create('despatch_discrepancies',  function($table) {
        $table->increments('id')->unsigned();
        $table->integer('pick_id')->unsigned();
        $table->foreign('pick_id')->references('id')->on('picks');
        $table->integer('pick_detail_id')->unsigned();
        $table->foreign('pick_detail_id')->references('id')->on('pick_details');
        $table->integer('original_qty')->unsigned();
        $table->integer('shipped_qty')->unsigned();
    });
}

public function down()
{
    Schema::drop('despatch_discrepancies');
}

Je dois changer cette table et supprimer la référence de clé étrangère & column pick_detail_id Et ajouter une nouvelle colonne varchar appelée sku après la colonne pick_id.

J'ai donc créé une autre migration, qui ressemble à ceci:

public function up()
{
    Schema::table('despatch_discrepancies', function($table)
    {
        $table->dropForeign('pick_detail_id');
        $table->dropColumn('pick_detail_id');
        $table->string('sku', 20)->after('pick_id');
    });
}

public function down()
{
    Schema::table('despatch_discrepancies', function($table)
    {
        $table->integer('pick_detail_id')->unsigned();
        $table->foreign('pick_detail_id')->references('id')->on('pick_details');
        $table->dropColumn('sku');
    });
}

Lorsque j'exécute cette migration, j'obtiens le message d'erreur suivant:

[Illuminate\Database\QueryException]
SQLSTATE [HY000]: Erreur générale: 1025 Erreur lors du changement de nom de './dev_iwms_reboot/despatch_discrepancies' en './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152) (SQL: alter table despatch_discrepancies Déposer la clé étrangère pick_detail_id)

[PDOException]
SQLSTATE [HY000]: Erreur générale: 1025 Erreur lors du changement de nom de './dev_iwms_reboot/despatch_discrepancies' en './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152)

Lorsque j'essaie d'inverser cette migration en exécutant la commande php artisan migrate:rollback, Je reçois un message Rolled back, Mais il ne fait rien dans la base de données.

Une idée de ce qui pourrait être faux? Comment peut-on supprimer une colonne qui a une référence de clé étrangère?

65
Latheesan

Il s'avère; quand vous créez une clé étrangère comme ceci:

$table->integer('pick_detail_id')->unsigned();
$table->foreign('pick_detail_id')->references('id')->on('pick_details');

Laravel nomme de manière unique la référence de clé étrangère comme suit:

<table_name>_<foreign_table_name>_<column_name>_foreign
despatch_discrepancies_pick_detail_id_foreign (in my case)

Par conséquent, lorsque vous souhaitez supprimer une colonne avec une référence de clé étrangère, vous devez procéder comme suit:

$table->dropForeign('despatch_discrepancies_pick_detail_id_foreign');
$table->dropColumn('pick_detail_id');

Mise à jour:

Laravel 4.2+ introduit une nouvelle convention de nommage:

<table_name>_<column_name>_foreign
68
Latheesan

Vous pouvez utiliser ceci:

$table->dropForeign(['pick_detail_id']);
$table->dropColumn('pick_detail_id');

Si vous prenez un pic chez dropForeign source, le nom de l'index de la clé étrangère sera créé si vous transmettez le nom de la colonne en tant que tableau.

121
Alex Pineda

J'avais plusieurs clés étrangères dans ma table, puis je devais supprimer les contraintes de clé étrangère une par une en passant le nom de la colonne à l'index du tableau dans la méthode down:

public function up()
{
    Schema::table('offices', function (Blueprint $table) {
        $table->unsignedInteger('country_id')->nullable();
        $table->foreign('country_id')
            ->references('id')
            ->on('countries')
            ->onDelete('cascade');

        $table->unsignedInteger('stateprovince_id')->nullable();
        $table->foreign('stateprovince_id')
            ->references('id')
            ->on('stateprovince')
            ->onDelete('cascade');
        $table->unsignedInteger('city_id')->nullable();
        $table->foreign('city_id')
            ->references('id')
            ->on('cities')
            ->onDelete('cascade');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('offices', function (Blueprint $table) {
        $table->dropForeign(['country_id']);
        $table->dropForeign(['stateprovince_id']);
        $table->dropForeign(['city_id']);
        $table->dropColumn(['country_id','stateprovince_id','city_id']);
    });
} 

L'utilisation de la déclaration ci-dessous ne fonctionne pas

$table->dropForeign(['country_id','stateprovince_id','city_id']); 

Parce que dropForeign ne les considère pas comme des colonnes distinctes que nous voulons supprimer. Nous devons donc les supprimer un à un.

16
Afraz Ahmad

Passer un tableau avec col name

$table->dropForeign(['user_id']);
11
Harry Bosh

La solution (pour moi) pour résoudre ce problème était de s'assurer que la commande $ table-> dropForeign () était transmise au bon nom de relation, pas nécessairement au nom de colonne. Vous ne voulez pas transmettre le nom de la colonne, ce qui serait beaucoup plus intuitif à mon humble avis.

Ce qui a fonctionné pour moi a été:

$table->dropForeign('local_table_foreign_id_foreign');
$table->column('foreign_id');

Ainsi, la chaîne que j'ai transmise à dropForeign () et qui a fonctionné pour moi était au format:

[table locale] _ [champ de clé étrangère] _ étranger

Si vous avez accès à un outil comme Sequel Pro ou Navicat, il vous sera très utile de pouvoir les visualiser.

9
DirtyBirdNJ

Je me suis dit que je ne savais pas où placer le bloc Schema::table.

Plus tard, j'ai découvert que la clé est sur l'erreur SQL:

[Illuminate\Database\QueryException]
SQLSTATE[23000]: Integrity constraint violation: 1217 Cannot delete or update a parent row: a foreign key constraint fails (SQL: drop table if exists `lu_benefits_categories`)

Donc, le bloc Schema::table Doit être inséré dans la fonction down() de la migration lu_benefits_categories Et avant la ligne Schema::dropIfExists:

public function down()
{
    Schema::table('table', function (Blueprint $table) {
        $table->dropForeign('table_category_id_foreign');
        $table->dropColumn('category_id');
    });
    Schema::dropIfExists('lu_benefits_categories');
}

Après cela, le php artisan migrate:refresh Ou php artisan migrate:reset Fera l'affaire.

4
Gus