Видалення стовпця із зовнішнім ключем Помилка 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');
}

Мені потрібно змінити цю таблицю та випустити посилання на зовнішній ключ та стовпець pick_detail_idта додати новий стовпець varchar, який називається skuпісля pick_idстовпця.

Отже, я створив чергову міграцію, яка виглядає так:

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' (таблиця помилок: 152: SQL) despatch_discrepanciesскинути зовнішній ключ pick_detail_id)

[PDOException]
SQLSTATE [HY000]: Загальна помилка: 1025 Помилка при перейменуванні './dev_iwms_reboot/despatch_discrepancies' в './dev_iwms_reboot/#sql2-67c-17c464' (помилка: 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
Робін ван Бален

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. <зовнішнє_назву_таблиці> не є частиною імені ключа. Він працює лише з <name_name> _ <name_column_name> _foreign.
багатий ремер

Я використовував його в laravel 4.2 і досі, це працює для мене.
Latheesan

2
<table_name>_<column_name>_foreignКонвенція по раніше здається, працює на 5,1
Яхья Uddin

Судячи з усього, відмовившись від стосунків, вам доведеться також скинути колонку. я думаю, що документація повинна була це також містити, оскільки можна легко припустити, що dropForeign також видалить стовпець. дякую за обмін. laravel.com/docs/5.0/schema#dropping-columns
Пікразма

Якщо хтось цікавився, індекси, які MySQL автоматично створює для зовнішніх ключів, скидаються, коли стовпці є. Не потрібно скидати їх вручну за допомогою $table->dropIndex('column_name').
Олександр

24

У мене в таблиці було кілька зовнішніх ключів, а потім мені довелося видаляти обмеження зовнішнього ключа по одному, передаючи ім'я стовпця як індекс масиву в методі 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']);
    });
} 

Використання наведеного нижче твердження не працює

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

Оскільки dropForeign не вважає їх окремими стовпцями, які ми хочемо видалити. Тож ми повинні скинути їх по одному.


Дякую, друже, додавання назви стовпця в масив мені підходить.
П'єр,

Якщо хтось цікавився, індекси, які MySQL автоматично створює для зовнішніх ключів, скидаються, коли стовпці є. Не потрібно скидати їх вручну за допомогою $table->dropIndex('column_name').
Олександр

9

Ключем (для мене) для вирішення цього було переконатися, що команді $ table-> dropForeign () передається правильне ім'я зв'язку, не обов'язково ім'я стовпця. Ви не хочете передавати назву стовпця, як це було б набагато інтуїтивнішим IMHO.

У мене спрацювало:

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

Тож рядок, який я передав dropForeign (), який працював для мене, був у форматі:

[локальна таблиця] _ [поле зовнішнього ключа] _зарубіжний

Якщо у вас є доступ до такого інструменту, як Sequel Pro або Navicat, можливість їх візуалізації буде дуже корисною.


Це чудово працює, я просто виявив, що це менш інтуїтивно, ніж оточення таблиці в дужках, як запропонував @Alex.
Марк Караван

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зробить свою справу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.