Colonna eliminata con chiave esterna Errore Laravel: Errore generale: 1025 Errore durante la ridenominazione


94

Ho creato una tabella utilizzando la migrazione in questo modo:

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

Devo cambiare questa tabella e rilasciare il riferimento alla chiave esterna e la colonna pick_detail_ide aggiungere una nuova colonna varchar chiamata skudopo la pick_idcolonna.

Quindi, ho creato un'altra migrazione, che assomiglia a questa:

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

Quando eseguo questa migrazione, ottengo il seguente errore:

[Illuminate \ Database \ QueryException]
SQLSTATE [HY000]: Errore generale: 1025 Errore durante la ridenominazione di './dev_iwms_reboot/despatch_discrepancies' in './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152) (SQL: alter table despatch_discrepanciesrilascia la chiave esterna pick_detail_id)

[PDOException]
SQLSTATE [HY000]: Errore generale: 1025 Errore durante la ridenominazione di "./dev_iwms_reboot/despatch_discrepancies" in "./dev_iwms_reboot/#sql2-67c-17c464" (errno: 152)

Quando provo a invertire questa migrazione eseguendo il php artisan migrate:rollbackcomando, ricevo un Rolled backmessaggio, ma in realtà non sta facendo nulla nel database.

Qualche idea su cosa potrebbe esserci di sbagliato? Come si rilascia una colonna che ha un riferimento a chiave esterna?

Risposte:


167

Puoi usare questo:

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

Se prendi un picco alla sorgente dropForeign, creerà il nome dell'indice della chiave esterna per te se passi il nome della colonna come array.


2
Anche la risposta accettata funziona: devi usare la giusta convenzione per il nome dell'indice. Ma questo è il problema anche con quella risposta: devi ricordare lo schema di denominazione per gli indici, mentre questa soluzione lo fa automaticamente! Ho sempre usato l'altro modo e mi sono sempre lamentato di quanto fosse poco pratico. Ora passo immediatamente a questa soluzione. Grazie mille!
Marco Pallante

6
Trucco fantastico. L'ho fatto a lungo come un idiota. Laravel potrebbe davvero usare un po 'di aiuto sui documenti. Potrei accettare la sfida ...
simonhamp

1
Ha funzionato per me in Laravel 5.0. Grazie mille, Alex!
SilithCrowe

1
Ha funzionato a meraviglia in Laravel 5.2.
ronin1184

3
Questo è un bel trucco. Molto più amichevole che ricordare la convenzione di denominazione delle chiavi esterne (che potrebbe cambiare in futuro). Come ha detto @ ronin1184, funziona perfettamente in Laravel 5.2
Robin van Baalen

81

Si scopre; quando crei una chiave esterna come questa:

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

Laravel nomina in modo univoco il riferimento alla chiave esterna in questo modo:

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

Pertanto, quando vuoi eliminare una colonna con riferimento a chiave esterna, devi farlo in questo modo:

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

Aggiornare:

Laravel 4.2+ introduce una nuova convenzione di denominazione:

<table_name>_<column_name>_foreign

4
Non funziona in Laravel 4.2. <foreign_table_name> non fa parte del nome della chiave. Funziona solo con <table_name> _ <column_name> _foreign.
Rich remer

L'ho usato in laravel 4.2 e lo faccio ancora, funziona per me.
Latheesan

2
La <table_name>_<column_name>_foreignconvention sembra ancora funzionare per 5.1
Yahya Uddin

Apparentemente, dopo aver abbandonato il vincolo sulla relazione, devi eliminare anche la colonna. Penso che la documentazione avrebbe dovuto includere anche questo perché si può facilmente presumere che dropForeign eliminerà anche la colonna. grazie per la condivisione. laravel.com/docs/5.0/schema#dropping-columns
Picrasma

Se qualcuno se lo stava chiedendo, gli indici che MySQL crea automaticamente per le chiavi esterne vengono eliminati quando le colonne sono. Non è necessario rilasciarli manualmente con $table->dropIndex('column_name').
Aleksandar

24

Avevo più chiavi esterne nella mia tabella e quindi ho dovuto rimuovere i vincoli di chiave esterna uno per uno passando il nome della colonna come indice dell'array nel metodo 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'utilizzo dell'istruzione seguente non funziona

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

Perché dropForeign non le considera colonne separate che vogliamo rimuovere. Quindi dobbiamo eliminarli uno per uno.


Grazie amico mio, l'aggiunta del nome della colonna in un array funziona per me.
Pierre

Se qualcuno se lo stava chiedendo, gli indici che MySQL crea automaticamente per le chiavi esterne vengono eliminati quando le colonne sono. Non è necessario rilasciarli manualmente con $table->dropIndex('column_name').
Aleksandar

9

La chiave (per me) per risolvere questo problema era assicurarsi che al comando $ table-> dropForeign () venisse passato il nome della relazione corretto, non necessariamente il nome della colonna. Non si desidera passare il nome della colonna, in quanto sarebbe molto più intuitivo IMHO.

Quello che ha funzionato per me è stato:

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

Quindi la stringa che ho passato a dropForeign () che ha funzionato per me era nel formato di:

[tabella locale] _ [campo chiave esterna] _estero

Se hai accesso a uno strumento come Sequel Pro o Navicat, essere in grado di visualizzarli sarà molto utile.


Funziona bene, l'ho trovato meno intuitivo rispetto a circondare il tavolo tra parentesi come suggerito da @Alex.
Mark Karavan

5

Qualcosa che mi è venuto in mente è stato che non sapevo dove mettere il Schema::tableblocco.

Successivamente ho scoperto che la chiave è sull'errore 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`)

Quindi il Schema::tableblocco deve andare nella down()funzione della lu_benefits_categoriesmigrazione e prima della Schema::dropIfExistsriga:

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

Dopodiché, php artisan migrate:refresho php artisan migrate:resetfarà il trucco.

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.