Menjatuhkan kolom dengan kunci asing Kesalahan Laravel: Kesalahan umum: 1025 Kesalahan saat mengganti nama

94

Saya telah membuat tabel menggunakan migrasi seperti ini:

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

Saya perlu mengubah tabel ini dan menjatuhkan referensi kunci asing & kolom pick_detail_iddan menambahkan kolom varchar baru yang disebut kolom skusetelah pick_id.

Jadi, saya telah membuat migrasi lain, yang terlihat seperti ini:

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

Saat saya menjalankan migrasi ini, saya mendapatkan error berikut:

[Illuminate \ Database \ QueryException]
SQLSTATE [HY000]: Kesalahan umum: 1025 Kesalahan saat mengganti nama './dev_iwms_reboot/despatch_discrepancies' menjadi './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152) (SQL: mengubah tabel despatch_discrepanciesjatuhkan pick_detail_id kunci asing)

[PDOException]
SQLSTATE [HY000]: Kesalahan umum: Kesalahan 1025 saat mengganti nama './dev_iwms_reboot/despatch_discrepancies' menjadi './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152)

Ketika saya mencoba membalikkan migrasi ini dengan menjalankan php artisan migrate:rollbackperintah, saya mendapat Rolled backpesan, tetapi sebenarnya tidak melakukan apa pun di database.

Tahu apa yang mungkin salah? Bagaimana Anda menjatuhkan kolom yang memiliki referensi kunci asing?

Bubut
sumber

Jawaban:

167

Anda dapat menggunakan ini:

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

Jika Anda mengambil puncak pada sumber dropForeign, itu akan membangun nama indeks kunci asing untuk Anda jika Anda meneruskan nama kolom sebagai array.

Alex Pineda
sumber
2
Jawaban yang diterima juga berfungsi: Anda harus menggunakan konvensi nama indeks yang benar. Tetapi ini juga masalah dengan jawaban itu: Anda harus mengingat skema penamaan untuk indeks, sementara solusi ini melakukannya secara otomatis! Saya selalu menggunakan cara lain, dan selalu mengeluh tentang betapa tidak praktisnya itu. Sekarang saya segera beralih ke solusi ini. Terima kasih banyak!
Marco Pallante
6
Trik yang luar biasa. Aku telah melakukannya jauh-jauh hari seperti orang bodoh. Laravel benar-benar membutuhkan bantuan di dokumen. Saya dapat mengambil tantangan ...
simonhamp
1
Bekerja untuk saya di Laravel 5.0. Terima kasih banyak, Alex!
SilithCrowe
1
Berfungsi seperti pesona di Laravel 5.2.
ronin1184
3
Ini adalah trik yang bagus. Jauh lebih ramah daripada mengingat konvensi penamaan kunci asing (yang mungkin berubah di masa mendatang). Seperti yang dikatakan @ ronin1184, bekerja dengan sempurna di Laravel 5.2
Robin van Baalen
81

Ternyata; ketika Anda membuat kunci asing seperti ini:

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

Laravel secara unik memberi nama referensi kunci asing seperti ini:

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

Oleh karena itu, ketika Anda ingin menjatuhkan kolom dengan referensi kunci asing, Anda harus melakukannya seperti ini:

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

Memperbarui:

Laravel 4.2+ memperkenalkan konvensi penamaan baru:

<table_name>_<column_name>_foreign
Bubut
sumber
4
Tidak berfungsi di Laravel 4.2. <foreign_table_name> bukan bagian dari nama kunci. Ia bekerja hanya dengan <table_name> _ <column_name> _foreign.
rich remer
Saya menggunakannya di laravel 4.2 dan masih melakukannya, itu berhasil untuk saya.
Latheesan
2
The <table_name>_<column_name>_foreignkonvensi nampaknya masih bekerja untuk 5.1
Yahya Uddin
Rupanya, setelah menghilangkan batasan pada hubungan, Anda juga harus menghapus kolom tersebut. Saya pikir dokumentasi harus menyertakan itu juga karena orang dapat dengan mudah berasumsi dropForeign juga akan menghapus kolom tersebut. terima kasih telah berbagi. laravel.com/docs/5.0/schema#dropping-columns
Picrasma
Jika ada yang bertanya-tanya, indeks yang dibuat secara otomatis oleh MySQL untuk kunci asing akan dihapus saat kolomnya. Tidak perlu menjatuhkannya secara manual dengan $table->dropIndex('column_name').
Aleksandar
24

Saya memiliki beberapa kunci asing di tabel saya dan kemudian saya harus menghapus batasan kunci asing satu per satu dengan mengirimkan nama kolom sebagai indeks array dalam metode turun:

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

Menggunakan pernyataan di bawah ini tidak berfungsi

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

Karena dropForeign tidak menganggapnya sebagai kolom terpisah yang ingin kita hapus. Jadi kita harus menjatuhkannya satu per satu.

Afraz Ahmad
sumber
Terima kasih teman saya, menambahkan nama kolom dalam array berfungsi untuk saya.
Pierre
Jika ada yang bertanya-tanya, indeks yang dibuat secara otomatis oleh MySQL untuk kunci asing akan dihapus saat kolomnya. Tidak perlu menjatuhkannya secara manual dengan $table->dropIndex('column_name').
Aleksandar
9

Kunci (bagi saya) untuk menyelesaikan ini adalah memastikan bahwa perintah $ table-> dropForeign () diberikan nama relasi yang benar, belum tentu nama kolomnya. Anda tidak ingin melewatkan nama kolom, karena IMHO akan jauh lebih intuitif.

Apa yang berhasil bagi saya adalah:

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

Jadi string yang saya berikan ke dropForeign () yang berhasil untuk saya adalah dalam format:

[tabel lokal] _ [bidang kunci asing] _foreign

Jika Anda memiliki akses ke alat seperti Sequel Pro atau Navicat, dapat memvisualisasikannya akan sangat membantu.

DirtyBirdNJ
sumber
Ini berfungsi dengan baik, saya hanya merasa kurang intuitif daripada mengelilingi tabel dalam tanda kurung seperti yang disarankan @Alex.
Mark Karavan
5

Sesuatu yang terpikir oleh saya adalah saya tidak tahu di mana harus meletakkan Schema::tableblok itu.

Kemudian saya menemukan bahwa kuncinya ada pada kesalahan 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`)

Jadi Schema::tableblok harus masuk dalam down()fungsi lu_benefits_categoriesmigrasi dan sebelum Schema::dropIfExistsbaris:

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

Setelah itu, php artisan migrate:refreshatau php artisan migrate:resetakan melakukan trik.

Gus
sumber