Descartar columna con clave externa Error de Laravel: Error general: 1025 Error al cambiar el nombre

7 minutos de lectura

Creé una tabla usando migración como esta:

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

Necesito cambiar esta tabla y eliminar la referencia y la columna de la clave externa pick_detail_id y agregue una nueva columna varchar llamada sku después pick_id columna.

Entonces, he creado otra migración, que se ve así:

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

Cuando ejecuto esta migración, aparece el siguiente error:

[Illuminate\Database\QueryException]

SQLSTATE[HY000]: Error general: 1025 Error al cambiar el nombre de ‘./dev_iwms_reboot/despatch_discrepancies’ a ‘./dev_iwms_reboot/#sql2-67c-17c464’ (errno: 152) (SQL: modificar tabla
despatch_discrepancies soltar clave foránea pick_detail_id)

[PDOException]

SQLSTATE[HY000]: Error general: 1025 Error al cambiar el nombre de ‘./dev_iwms_reboot/despatch_discrepacies’ a ‘./dev_iwms_reboot/#sql2-67c-17c464’ (errno: 152)

Cuando intento revertir esta migración ejecutando php artisan migrate:rollback comando, obtengo un Rolled back mensaje, pero en realidad no está haciendo nada en la base de datos.

¿Alguna idea de lo que podría estar mal? ¿Cómo se suelta una columna que tiene una referencia de clave externa?

avatar de usuario
Álex Pineda

Puedes usar esto:

Schema::table('despatch_discrepancies', function (Blueprint $table) {
    $table->dropForeign(['pick_detail_id']);
    $table->dropColumn('pick_detail_id');
});

Si toma un pico en la fuente dropForeign, creará el nombre del índice de clave externa para usted si pasa el nombre de la columna como una matriz.

  • La respuesta aceptada también funciona: debe usar la convención de nombre de índice correcta. Pero este es el problema con esa respuesta también: debe recordar el esquema de nombres para los índices, ¡mientras que esta solución lo hace automáticamente! Siempre usé la otra manera, y siempre me quejé de lo poco práctico que era. Ahora estoy cambiando inmediatamente a esta solución. ¡Muchos gracias!

    – Marco Pallante

    16 de julio de 2015 a las 15:48

  • Impresionante truco. Lo he estado haciendo durante mucho tiempo como un tonto. Laravel realmente podría usar algo de ayuda en los documentos. Puedo aceptar el reto…

    – simonhamp

    13 de diciembre de 2015 a las 1:03

  • Trabajó para mí en Laravel 5.0. ¡Muchas gracias, Álex!

    – SilithCrowe

    20 de enero de 2016 a las 18:15

  • Funcionó a las mil maravillas en Laravel 5.2.

    – Hijo Tran

    23 de marzo de 2016 a las 7:30

  • Este es un buen truco. Mucho más amigable que recordar la convención de nomenclatura de claves externas (que podría cambiar en el futuro). Como dijo @ ronin1184, funciona perfectamente en Laravel 5.2

    –Robin van Baalen

    17 de junio de 2016 a las 16:07

avatar de usuario
Latheesan

Resulta; cuando creas una clave foránea como esta:

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

Laravel nombra de forma única la referencia de clave externa de esta manera:

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

Por lo tanto, cuando desee eliminar una columna con una referencia de clave externa, debe hacerlo así:

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

Actualizar:

Laravel 4.2+ introduce una nueva convención de nomenclatura:

<table_name>_<column_name>_foreign

  • No funciona en Laravel 4.2. no forma parte del nombre de la clave. Funciona solo con __foreign.

    – recuerdo rico

    3 de abril de 2015 a las 1:18

  • Lo usé en laravel 4.2 y todavía lo hago, funciona para mí.

    – Latheesan

    12 de junio de 2015 a las 11:40

  • los <table_name>_<column_name>_foreign la convención todavía parece funcionar para 5.1

    – Yahya Udin

    25 de diciembre de 2015 a las 15:43


  • Aparentemente, después de eliminar la restricción de la relación, también debe eliminar la columna. Creo que la documentación también debería haberlo incluido porque uno puede suponer fácilmente que dropForeign también eliminará la columna. gracias por compartir laravel.com/docs/5.0/schema#dropping-columns

    – Picrasma

    26 de junio de 2016 a las 15:15


  • Si alguien se preguntaba, los índices que MySQL crea automáticamente para claves foráneas se eliminan cuando se eliminan las columnas. No es necesario soltarlos manualmente con $table->dropIndex('column_name').

    – Aleksandar

    27 de marzo de 2019 a las 8:46

Tenía varias claves externas en mi tabla y luego tuve que eliminar las restricciones de clave externa una por una pasando el nombre de la columna como índice de la matriz en el método 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']);
    });
} 

Usar la siguiente declaración no funciona

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

Porque dropForeign no las considera columnas separadas que queremos eliminar. Así que tenemos que soltarlos uno por uno.

  • Gracias amigo, agregar el nombre de la columna en una matriz funciona para mí.

    – Pedro

    16 de julio de 2018 a las 1:57

  • Si alguien se preguntaba, los índices que MySQL crea automáticamente para claves foráneas se eliminan cuando se eliminan las columnas. No es necesario soltarlos manualmente con $table->dropIndex('column_name').

    – Aleksandar

    27 de marzo de 2019 a las 8:55

  • ty, quería Schema::table('offices', function (Blueprint $table) {} muy malo…

    – Akshay K Nair

    24 de abril de 2021 a las 17:01

  • por alguna razón, laravel no antepone el nombre de la tabla y el postfijo ‘extranjero’ en dropForeign. así que creo que debería ser: $table->dropForeign(['offices_country_id_foreign']);

    – Sumit Wadhwa

    9 dic 2021 a las 15:33


avatar de usuario
SucioPájaroNJ

La clave (para mí) para resolver esto fue asegurarme de que el comando $table->dropForeign() pasara el nombre de relación correcto, no necesariamente el nombre de la columna. Tú haces no quiero pasar el nombre de la columna, ya que sería mucho más intuitivo en mi humilde opinión.

Lo que funcionó para mí fue:

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

Entonces, la cadena que pasé a dropForeign() que funcionó para mí tenía el formato de:

[local table]_[foreign key field]_extranjero

Si tiene acceso a una herramienta como Sequel Pro o Navicat, poder visualizarlos será muy útil.

Algo que se me ocurrio es que no sabia donde poner el Schema::table bloquear.

Más tarde descubrí que la clave está en el error de 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`)

Entonces el Schema::table el bloque debe ir en el down() función de la lu_benefits_categories la migración y antes de la Schema::dropIfExists línea:

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

Después de eso, el php artisan migrate:refresh o php artisan migrate:reset hará el truco.

avatar de usuario
Felipe Mansano

en laravel 8 uso soltarRestringidoForeignId
(https://github.com/laravel/framework/pull/34806)

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddAddressFieldsInEventTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        
        Schema::table('events', function (Blueprint $table) {
            $table->bigInteger('address_id')->nullable();

            $table->foreign('address_id')
                ->references('id')
                ->on('addresses')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('events', function (Blueprint $table) {
            $table->dropConstrainedForeignId('address_id');
            $table->dropColumn('address_id');
        });
    }
}

avatar de usuario
Riki Krismawan

Puede deshabilitar la identificación de la relación primero

Schema::disableForeignKeyConstraints();

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad