Spalte mit Fremdschlüssel löschen Laravel-Fehler: Allgemeiner Fehler: 1025 Fehler beim Umbenennen

91

Ich habe eine Tabelle mit folgender Migration erstellt:

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

Ich muss diese Tabelle ändern und die Fremdschlüsselreferenz & Spalte pick_detail_idlöschen und eine neue varchar-Spalte hinzufügen, die skunach der pick_idSpalte aufgerufen wird.

Also habe ich eine weitere Migration erstellt, die folgendermaßen aussieht:

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

Wenn ich diese Migration ausführe, wird folgende Fehlermeldung angezeigt:

[Illuminate \ Database \ QueryException]
SQLSTATE [HY000]: Allgemeiner Fehler: 1025 Fehler beim Umbenennen von './dev_iwms_reboot/despatch_discrepancies' in './dev_iwms_reboot/#sql2-67c-17c464' (Fehler: 152) (SQL: alter table) despatch_discrepanciesFremdschlüssel löschen pick_detail_id)

[PDOException]
SQLSTATE [HY000]: Allgemeiner Fehler: 1025 Fehler beim Umbenennen von './dev_iwms_reboot/despatch_discrepancies' in './dev_iwms_reboot/#sql2-67c-17c464' (Fehler: 152)

Wenn ich versuche, diese Migration durch Ausführen eines php artisan migrate:rollbackBefehls rückgängig zu machen , wird eine Rolled backMeldung angezeigt, die jedoch in der Datenbank nichts bewirkt.

Irgendeine Idee, was falsch sein könnte? Wie löscht man eine Spalte mit einer Fremdschlüsselreferenz?

Latheesan
quelle

Antworten:

160

Sie können dies verwenden:

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

Wenn Sie einen Peak an der dropForeign-Quelle nehmen, wird der Fremdschlüsselindexname für Sie erstellt, wenn Sie den Spaltennamen als Array übergeben.

Alex Pineda
quelle
2
Die akzeptierte Antwort funktioniert auch: Sie müssen die richtige Indexnamenkonvention verwenden. Dies ist aber auch das Problem mit dieser Antwort: Sie müssen sich das Namensschema für Indizes merken, während diese Lösung dies automatisch tut! Ich habe immer den anderen Weg benutzt und mich immer darüber beschwert, wie unpraktisch es war. Jetzt wechsle ich sofort zu dieser Lösung. Vielen Dank!
Marco Pallante
6
Genialer Trick. Ich habe es den langen Weg wie ein Trottel gemacht. Laravel könnte wirklich Hilfe bei den Dokumenten gebrauchen. Ich kann die Herausforderung
annehmen
1
Arbeitete für mich in Laravel 5.0. Vielen Dank, Alex!
SilithCrowe
1
Arbeitete wie ein Zauber in Laravel 5.2.
Ronin1184
3
Das ist ein ordentlicher Trick. Viel freundlicher als das Erinnern an die Fremdschlüssel-Namenskonvention (die sich in Zukunft ändern könnte). Wie @ ronin1184 sagte, funktioniert perfekt in Laravel 5.2
Robin van Baalen
80

Es stellt sich heraus; Wenn Sie einen Fremdschlüssel wie folgt erstellen:

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

Laravel benennt die Fremdschlüsselreferenz eindeutig wie folgt:

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

Wenn Sie eine Spalte mit Fremdschlüsselreferenz löschen möchten, müssen Sie dies folgendermaßen tun:

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

Aktualisieren:

Laravel 4.2+ führt eine neue Namenskonvention ein:

<table_name>_<column_name>_foreign
Latheesan
quelle
4
Funktioniert nicht in Laravel 4.2. <foreign_table_name> ist nicht Teil des Schlüsselnamens. Es funktioniert nur mit <Tabellenname> _ <Spaltenname> _foreign.
Rich Remer
Ich habe es in Laravel 4.2 verwendet und es funktioniert immer noch für mich.
Latheesan
2
Die <table_name>_<column_name>_foreignKonvention scheint immer noch für 5.1 zu funktionieren
Yahya Uddin
Anscheinend müssen Sie nach dem Löschen der Einschränkung für die Beziehung auch die Spalte löschen. Ich denke, die Dokumentation hätte das auch enthalten sollen, da man leicht davon ausgehen kann, dass dropForeign auch die Spalte löscht. danke für das teilen. laravel.com/docs/5.0/schema#dropping-columns
Picrasma
Wenn sich jemand gefragt hat, werden Indizes, die MySQL automatisch für Fremdschlüssel erstellt, gelöscht, wenn die Spalten vorhanden sind. Sie müssen nicht manuell mit gelöscht werden $table->dropIndex('column_name').
Aleksandar
22

Ich hatte mehrere Fremdschlüssel in meiner Tabelle und musste dann nacheinander Fremdschlüsseleinschränkungen entfernen, indem ich den Spaltennamen als Index des Arrays in der Down-Methode übergab:

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

Die Verwendung der folgenden Anweisung funktioniert nicht

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

Da dropForeign sie nicht als separate Spalten betrachtet, die wir entfernen möchten. Also müssen wir sie einzeln fallen lassen.

Afraz Ahmad
quelle
Vielen Dank, mein Freund, das Hinzufügen des Spaltennamens in einem Array funktioniert für mich.
Pierre
Wenn sich jemand gefragt hat, werden Indizes, die MySQL automatisch für Fremdschlüssel erstellt, gelöscht, wenn die Spalten vorhanden sind. Sie müssen nicht manuell mit gelöscht werden $table->dropIndex('column_name').
Aleksandar
12

Übergeben Sie ein Array mit dem Spaltennamen

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

Der Schlüssel (für mich) zur Lösung dieses Problems bestand darin, sicherzustellen, dass dem Befehl $ table-> dropForeign () der richtige Beziehungsname übergeben wurde, nicht unbedingt der Spaltenname. Sie nicht wollen , die Spaltennamen zu übergeben, wie es wäre viel intuitiver IMHO.

Was für mich funktioniert hat war:

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

Die Zeichenfolge, die ich an dropForeign () übergeben habe und die für mich funktioniert hat, hatte folgendes Format:

[lokale Tabelle] _ [Fremdschlüsselfeld] _foreign

Wenn Sie Zugriff auf ein Tool wie Sequel Pro oder Navicat haben, ist es sehr hilfreich, diese zu visualisieren.

DirtyBirdNJ
quelle
Dies funktioniert gut, ich fand es nur weniger intuitiv als die Tabelle in Klammern zu setzen, wie @Alex vorgeschlagen hat.
Mark Karavan
5

Mir fiel ein, dass ich nicht wusste, wo ich den Schema::tableBlock platzieren sollte.

Später stellte ich fest, dass sich der Schlüssel im SQL-Fehler befindet:

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

Der Schema::tableBlock muss also in der down()Funktion der lu_benefits_categoriesMigration und vor der Schema::dropIfExistsZeile stehen:

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

Danach macht das php artisan migrate:refreshoder php artisan migrate:resetden Trick.

Gus
quelle