Laravel Schema onDelete establece nulo

112

No puedo averiguar cómo establecer la restricción onDelete adecuada en una tabla en Laravel. (Estoy trabajando con SqLite)

$table->...->onDelete('cascade'); // works
$table->...->onDelete('null || set null'); // neither of them work

Tengo 3 migraciones, creando la tabla de la galería:

Schema::create('galleries', function($table)
{
    $table->increments('id');
    $table->string('name')->unique();
    $table->text('path')->unique();
    $table->text('description')->nullable();
    $table->timestamps();
    $table->engine = 'InnoDB';
});

Creando la tabla de imágenes:

Schema::create('pictures', function($table)
{
    $table->increments('id');
    $table->text('path');
    $table->string('title')->nullable();
    $table->text('description')->nullable();
    $table->integer('gallery_id')->unsigned();
    $table->foreign('gallery_id')
        ->references('id')->on('galleries')
        ->onDelete('cascade');
    $table->timestamps();
    $table->engine = 'InnoDB';
});

Vinculación de la tabla de la galería a una imagen:

Schema::table('galleries', function($table)
{
    // id of a picture that is used as cover for a gallery
    $table->integer('picture_id')->after('description')
        ->unsigned()->nullable();
    $table->foreign('picture_id')
        ->references('id')->on('pictures')
        ->onDelete('cascade || set null || null'); // neither of them works
});

No recibo ningún error. Además, incluso la opción "cascada" no funciona (solo en la tabla de la galería). Eliminar una galería elimina todas las imágenes. Pero eliminar la imagen de portada no eliminará la galería (con fines de prueba).

Dado que incluso la "cascada" no se activa, "establecer nulo" no es el problema.

EDITAR (solución alternativa):

Después de leer este artículo , cambié un poco mi esquema. Ahora, la tabla de imágenes contiene una celda "is_cover", que indica si esta imagen es una portada de su álbum o no.

¡Aún se agradece mucho una solución al problema original!

MK
fuente

Respuestas:

318

Si desea establecer un valor nulo al eliminar:

$table->...->onDelete('set null');

Primero asegúrese de establecer el campo de clave externa como anulable:

$table->integer('foreign_id')->unsigned()->nullable();
Johan
fuente
37
más para->nullable()
mohsenJsh
3
¿Hay alguna documentación de Laravel sobre esto?
Chuck Le Butt
laravel.com/docs/6.x/migrations#foreign-key-constraints no documenta qué opciones hay, pero creo que puede asumir que son los valores predeterminados de mysql (ver ../ vendor / laravel / framework / src / Illuminate / Database / Schema / Grammars / Grammar.php)
Dirk
6
  • Este es un problema conocido en Laravel. Más información sobre esto aquí .

  • Esta función no es compatible con SQLite, consulte aquí

  • También un tema que tiene un enfrentamiento detallado de este problema.

MK
fuente
1
@SimonBengtsson El problema debe haberse cerrado o eliminado.
MK
5

De acuerdo a

http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html

$ table-> onDelete ('set null') debería funcionar tal vez intente

$table->...->onDelete(DB::raw('set null'));

Si hay algún error, también sería útil

Chris Barrett
fuente
Es posible que desee retroceder, escribir el sql a mano y luego ejecutar y ejecutar pruebas en local. Todo lo que puedo encontrar dice que debería funcionar dev.mysql.com/doc/refman/5.6/en/… , podría ser un problema al generar el sql
Chris Barrett
¡Gracias! Desafortunadamente, resultó en el mismo problema. Creo que es algo específico de SqLite y referencias circulares.
MK
Más uno porque onDelete ('set null') funciona con mysql.
Simon Bengtsson
3

Usando Laravel 4.2 en MySQL 5.5 con InnoDB, funciona onDelete ('set null').

Mark Kendall
fuente