การวางคอลัมน์ที่มีข้อผิดพลาด Laravel ของคีย์ต่างประเทศ: ข้อผิดพลาดทั่วไป: 1025 ข้อผิดพลาดในการเปลี่ยนชื่อ


94

ฉันได้สร้างตารางโดยใช้การโยกย้ายดังนี้:

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

ฉันต้องการเปลี่ยนตารางนี้และวางการอ้างอิงและคอลัมน์ Foreign Key pick_detail_idและเพิ่มคอลัมน์ varchar ใหม่ที่เรียกว่าskuafter pick_idcolumn

ฉันได้สร้างการย้ายข้อมูลอีกครั้งซึ่งมีลักษณะดังนี้:

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

เมื่อฉันเรียกใช้การย้ายข้อมูลนี้ฉันได้รับข้อผิดพลาดต่อไปนี้:

[Illuminate \ Database \ QueryException]
SQLSTATE [HY000]: ข้อผิดพลาดทั่วไป: 1025 ข้อผิดพลาดในการเปลี่ยนชื่อของ './dev_iwms_reboot/despatch_discrepancies' เป็น './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152) (SQL: alter table despatch_discrepanciesวางคีย์ต่างประเทศ pick_detail_id)

[PDOException]
SQLSTATE [HY000]: ข้อผิดพลาดทั่วไป: ข้อผิดพลาด 1025 ในการเปลี่ยนชื่อของ "./dev_iwms_reboot/despatch_discrepancies 'เป็น' ./dev_iwms_reboot/#sql2-67c-17c464 '(errno: 152)

เมื่อฉันพยายามย้อนกลับการย้ายข้อมูลโดยเรียกใช้php artisan migrate:rollbackคำสั่งฉันได้รับRolled backข้อความ แต่มันไม่ได้ทำอะไรเลยในฐานข้อมูล

มีความคิดอะไรผิดหรือเปล่า? คุณวางคอลัมน์ที่มีการอ้างอิงคีย์ต่างประเทศได้อย่างไร

คำตอบ:


167

คุณสามารถใช้สิ่งนี้:

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

หากคุณใช้จุดสูงสุดที่แหล่งที่มา dropForeign มันจะสร้างชื่อดัชนีคีย์ต่างประเทศให้คุณหากคุณส่งชื่อคอลัมน์เป็นอาร์เรย์


2
คำตอบที่ยอมรับก็ใช้ได้เช่นกัน: คุณต้องใช้หลักการชื่อดัชนีที่ถูกต้อง แต่นี่ก็เป็นปัญหาของคำตอบนั้นเช่นกันคุณต้องจำรูปแบบการตั้งชื่อสำหรับดัชนีในขณะที่โซลูชันนี้ทำโดยอัตโนมัติ! ฉันมักจะใช้วิธีอื่นและมักจะบ่นเสมอว่ามันใช้ไม่ได้ผล ตอนนี้ฉันเปลี่ยนมาใช้โซลูชันนี้ทันที ขอบคุณมาก!
Marco Pallante

6
เคล็ดลับน่ากลัว ฉันทำมานานแล้วเหมือนคนดูด Laravel สามารถใช้ความช่วยเหลือบางอย่างกับเอกสารได้ ฉันอาจจะรับความท้าทาย ...
simonhamp

1
ทำงานให้ฉันใน Laravel 5.0 ขอบคุณมากอเล็กซ์!
SilithCrowe

1
ทำงานได้อย่างมีเสน่ห์ใน Laravel 5.2
ronin1184

3
นี่เป็นเคล็ดลับที่เรียบร้อย เป็นมิตรกว่าการจำหลักการตั้งชื่อคีย์ภาษาต่างประเทศ (ซึ่งอาจมีการเปลี่ยนแปลงในอนาคต) เช่นเดียวกับที่ @ ronin1184 กล่าวว่าทำงานได้อย่างสมบูรณ์ใน Laravel 5.2
Robin van Baalen

81

ปรากฎว่า; เมื่อคุณสร้างคีย์ต่างประเทศเช่นนี้:

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

Laravel ตั้งชื่อการอ้างอิงคีย์ต่างประเทศโดยไม่ซ้ำกันดังนี้:

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

ดังนั้นเมื่อคุณต้องการวางคอลัมน์ที่มีการอ้างอิงคีย์ต่างประเทศคุณต้องทำดังนี้:

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

อัปเดต:

Laravel 4.2+ นำเสนอหลักการตั้งชื่อใหม่:

<table_name>_<column_name>_foreign

4
ไม่ทำงานใน Laravel 4.2 <foreign_table_name> ไม่ใช่ส่วนหนึ่งของชื่อคีย์ ใช้งานได้กับ <table_name> _ <column_name> _foreign
rich remer

ฉันใช้มันใน laravel 4.2 และยังคงใช้งานได้สำหรับฉัน
โรงกลึง

2
การ<table_name>_<column_name>_foreignประชุมยังคงใช้งานได้สำหรับ 5.1
Yahya Uddin

เห็นได้ชัดว่าหลังจากวางข้อ จำกัด เกี่ยวกับความสัมพันธ์แล้วคุณต้องวางคอลัมน์ด้วย ฉันคิดว่าเอกสารควรรวมไว้ด้วยเพราะใคร ๆ ก็สามารถสมมติว่า dropForeign จะลบคอลัมน์ได้ ขอบคุณสำหรับการแบ่งปัน laravel.com/docs/5.0/schema#dropping-columns
Picrasma

หากใครสงสัยดัชนีที่ MySQL สร้างขึ้นโดยอัตโนมัติสำหรับคีย์ต่างประเทศจะถูกทิ้งเมื่อคอลัมน์อยู่ $table->dropIndex('column_name')ไม่จำเป็นต้องวางไว้ด้วยตนเอง
Aleksandar

24

ฉันมีคีย์ต่างประเทศหลายรายการในตารางของฉันจากนั้นฉันต้องลบข้อ จำกัด ของคีย์ต่างประเทศทีละรายการโดยส่งชื่อคอลัมน์เป็นดัชนีของอาร์เรย์ในวิธีการลง:

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

ใช้คำสั่งด้านล่างไม่ได้ผล

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

เนื่องจาก dropForeign ไม่พิจารณาพวกเขาแยกคอลัมน์ที่เราต้องการลบ เราจึงต้องวางทีละรายการ


ขอบคุณเพื่อนของฉันการเพิ่มชื่อคอลัมน์ในอาร์เรย์ใช้ได้ผลกับฉัน
ปิแอร์

หากใครสงสัยดัชนีที่ MySQL สร้างขึ้นโดยอัตโนมัติสำหรับคีย์ต่างประเทศจะถูกทิ้งเมื่อคอลัมน์อยู่ $table->dropIndex('column_name')ไม่จำเป็นต้องวางไว้ด้วยตนเอง
Aleksandar

9

กุญแจสำคัญ (สำหรับฉัน) ในการแก้ปัญหานี้คือเพื่อให้แน่ใจว่าคำสั่ง $ table-> dropForeign () ถูกส่งผ่านชื่อความสัมพันธ์ที่ถูกต้องไม่จำเป็นต้องเป็นชื่อคอลัมน์ คุณไม่ต้องการส่งชื่อคอลัมน์เช่นเดียวกับ IMHO ที่ใช้งานง่ายกว่ามาก

สิ่งที่ได้ผลสำหรับฉันคือ:

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

ดังนั้นสตริงที่ฉันส่งไปยัง dropForeign () ที่เหมาะกับฉันอยู่ในรูปแบบของ:

[ตารางท้องถิ่น] _ [ฟิลด์คีย์ต่างประเทศ] _foreign

หากคุณสามารถเข้าถึงเครื่องมือเช่น Sequel Pro หรือ Navicat ได้การมองเห็นภาพเหล่านั้นจะเป็นประโยชน์มาก


ใช้งานได้ดีฉันเพิ่งพบว่ามันใช้งานง่ายน้อยกว่ารอบ ๆ ตารางในวงเล็บตามที่ @Alex แนะนำ
Mark Karavan

5

สิ่งที่เกิดขึ้นกับฉันคือฉันไม่รู้ว่าจะวางไฟล์ Schema::tableบล็อกไว้ที่ไหน

ต่อมาฉันพบว่าคีย์อยู่ในข้อผิดพลาด 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`)

ดังนั้นSchema::tableบล็อกจึงต้องอยู่ในdown()หน้าที่ของการlu_benefits_categoriesย้ายข้อมูลและก่อน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');
}

หลังจากนั้นphp artisan migrate:refreshหรือphp artisan migrate:resetจะทำเคล็ดลับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.