Yabancı anahtarla sütun düşüyor Laravel hatası: Genel hata: 1025 Yeniden adlandırma hatası


94

Taşıma işlemini şu şekilde kullanarak bir tablo oluşturdum:

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

Bu tabloyu değiştirmem ve yabancı anahtar referansını ve sütununu pick_detail_idbırakmam ve sütundan skusonra adlandırılan yeni bir varchar sütunu eklemem gerekiyor pick_id.

Bu yüzden, şuna benzeyen başka bir geçiş oluşturdum:

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

Bu taşımayı çalıştırdığımda şu hatayı alıyorum:

[Illuminate \ Database \ QueryException]
SQLSTATE [HY000]: Genel hata: 1025 './dev_iwms_reboot/despatch_discrepancies' için './dev_iwms_reboot/#sql2-67c-17c464' (hata no: 152) (SQL: tabloyu değiştir despatch_discrepanciesyabancı anahtarı bırak pick_detail_id)

[PDOException]
SQLSTATE [HY000]: Genel hata: 1025 './dev_iwms_reboot/despatch_discrepancies' olarak './dev_iwms_reboot/#sql2-67c-17c464' olarak yeniden adlandırılırken hata (hata no: 152)

php artisan migrate:rollbackKomut çalıştırarak bu geçişi tersine çevirmeye çalıştığımda bir Rolled backmesaj alıyorum, ancak aslında veritabanında hiçbir şey yapmıyor.

Neyin yanlış olabileceği hakkında bir fikriniz var mı? Yabancı anahtar referansı olan bir sütunu nasıl bırakırsınız?

Yanıtlar:


167

Bunu kullanabilirsiniz:

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

DropForeign kaynağında zirve yaparsanız, sütun adını bir dizi olarak iletirseniz, yabancı anahtar dizin adını sizin için oluşturacaktır.


2
Kabul edilen cevap da işe yarıyor: doğru dizin adı kuralını kullanmalısınız. Ancak bu yanıtla ilgili sorun da budur: bu çözüm otomatik olarak yaparken dizinler için adlandırma şemasını hatırlamanız gerekir! Her zaman diğer yolu kullandım ve her zaman bunun ne kadar pratik olmadığından şikayet ettim. Şimdi hemen bu çözüme geçiyorum. Çok teşekkür ederim!
Marco Pallante

6
Harika numara. Uzun zamandır bunu bir aptal gibi yapıyorum. Laravel gerçekten dokümanlar için biraz yardım kullanabilir. Meydan okumaya
başlayabilirim

1
Benim için Laravel 5.0'da çalıştı. Çok teşekkürler Alex!
SilithCrowe

1
Laravel 5.2'de bir cazibe gibi çalıştı.
ronin1184

3
Bu harika bir numara. Yabancı anahtar adlandırma kuralını (gelecekte değişebilir) hatırlamaktan çok daha dostça. @ Ronin1184'ün dediği gibi, Laravel 5.2'de mükemmel çalışıyor
Robin van Baalen

81

Görünüşe göre; bunun gibi bir yabancı anahtar oluşturduğunuzda:

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

Laravel, yabancı anahtar referansını şu şekilde benzersiz bir şekilde adlandırır:

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

Bu nedenle, yabancı anahtar referansı olan bir sütun bırakmak istediğinizde, bunu şu şekilde yapmanız gerekir:

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

Güncelleme:

Laravel 4.2+ yeni bir adlandırma kuralı sunar:

<table_name>_<column_name>_foreign

4
Laravel 4.2'de çalışmaz. <foreign_table_name>, anahtar adının bir parçası değil. Yalnızca <table_name> _ <column_name> _foreign ile çalışır.
zengin yeniden

Laravel 4.2'de kullandım ve hala kullanıyorum, benim için çalışıyor.
Latheesan

2
<table_name>_<column_name>_foreignKongre hala 5.1 için işin görünüyor
Yahya Uddin

Görünüşe göre, ilişkideki kısıtlamayı kaldırdıktan sonra, sütunu da bırakmanız gerekiyor. Sanırım dokümantasyon bunu da içermelidir çünkü kolaylıkla dropForeign'ın sütunu sileceğini varsayabiliriz. paylaşım için teşekkürler. laravel.com/docs/5.0/schema#dropping-columns
Picrasma

Merak eden biri varsa, MySQL'in yabancı anahtarlar için otomatik olarak oluşturduğu dizinler, sütunlar olduğunda bırakılır. Manuel olarak düşürmenize gerek yok $table->dropIndex('column_name').
Aleksandar

24

Tablomda birden fazla yabancı anahtar vardı ve sonra yabancı anahtar kısıtlamalarını tek tek sütun adını aşağı yöntemde dizinin dizini olarak ileterek kaldırmak zorunda kaldım:

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

Aşağıdaki ifadeyi kullanmak işe yaramıyor

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

Çünkü dropForeign, bunları kaldırmak istediğimiz ayrı sütunlar olarak kabul etmez. Bu yüzden onları birer birer düşürmeliyiz.


Teşekkürler arkadaşım, sütun adını bir diziye eklemek benim için çalışıyor.
Pierre

Merak eden biri varsa, MySQL'in yabancı anahtarlar için otomatik olarak oluşturduğu dizinler, sütunlar olduğunda bırakılır. Manuel olarak düşürmenize gerek yok $table->dropIndex('column_name').
Aleksandar

9

Bunu çözmenin anahtarı (benim için) $ table-> dropForeign () komutunun mutlaka sütun adı değil, doğru ilişki adıyla geçirildiğinden emin olmaktı. Sen do not olarak çok daha sezgisel IMHO olurdu, sütun adını geçmek istiyorum.

Benim için işe yarayan şuydu:

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

Bu nedenle, benim için çalışan dropForeign () 'a geçirdiğim dize şu biçimdeydi:

[yerel tablo] _ [yabancı anahtar alanı] _foreign

Sequel Pro veya Navicat gibi bir araca erişiminiz varsa, bunları görselleştirebilmeniz çok yardımcı olacaktır.


Bu iyi çalışıyor, sadece @Alex'in önerdiği gibi tabloyu parantez içinde çevrelemekten daha az sezgisel buldum.
Mark Karavan

5

Başıma gelen bir şey, Schema::tablebloğu nereye koyacağımı bilmememdi .

Daha sonra anahtarın SQL hatası üzerinde olduğunu keşfettim:

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

Dolayısıyla Schema::tablebloğun geçiş down()işlevinde lu_benefits_categoriesve Schema::dropIfExistssatırdan önce gitmesi gerekir :

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

Bundan sonra, php artisan migrate:refreshya php artisan migrate:resetda hile yapacak.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.