【问题标题】:Delete each corresponding row in One-to-One relationship on delete of either在删除任何一个时删除一对一关系中的每个对应行
【发布时间】:2017-10-15 14:27:08
【问题描述】:

我正在尝试学习一对一的关系。我正在使用 Laravel 5.5.13。

我的简单应用是这样的:

我创建了一个App\Message。我可以选择将App\Task 与它关联。

我的目标:

  • 一旦关联了App\Task,如果任务被删除,它应该级联删除App\Message行。
  • 反之,如果App\Message被删除,它应该级联删除App\Task行。

但是我在迁移时遇到错误,因为tasks_table 是在messages_table 之后创建的。

这是我的迁移:

2017_10_15_021803_create_messages_table.php:

public function up()
{
    Schema::create('messages', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('task_id')->unsigned()->nullable();
        $table->text('body');
        $table->timestamps();

        $table->foreign('task_id')->references('id')->on('tasks')->onDelete('cascade'); //// IF I COMMENT THIS OUT THE MIGRATION WORKS, BUT I NEED THIS IN

    });
}

对于App\Task2017_10_15_023343_create_tasks_table.php

public function up()
{
    Schema::create('tasks', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('message_id')->unsigned();
        $table->timestamps();

        $table->foreign('message_id')->references('id')->on('messages')->onDelete('cascade');
    });
}

如果我注释掉$table->foreign('task_id')->references('id')->on('tasks')->onDelete('cascade');,那么迁移工作,但我需要在删除任务时删除消息,并且没有这一行就不会发生。

我运行php artisan migrate后得到的错误是:

[照亮\数据库\查询异常] SQLSTATE[HY000]: 一般错误: 1005 Can't create table petfolk.#sql-42e8_16f (errno: 150 "外键约束格式不正确") (SQL: alter table messages add constraint messages_task_id_foreign foreign key ( task_id) 在删除集上引用 tasks (id) 为空)

[PDO异常] SQLSTATE[HY000]: 一般错误: 1005 无法创建表petfolk.#sql-42e8_16f (errno: 150 "外键约束格式不正确")

【问题讨论】:

  • 你得到什么错误?
  • 感谢@OmarTarek 的快速回复和提醒!我添加了错误信息。谢谢!

标签: laravel laravel-5.5


【解决方案1】:

只需创建第三个迁移并在迁移中移动外键添加逻辑:

Schema::table('messages', function (Blueprint $table) {
    $table->foreign('task_id')->references('id')->on('tasks')->onDelete('cascade');
}

当两个表都被创建时它会起作用。

【讨论】:

  • Ohhhh 错误是因为还没有 MESSAGES 表!!!不是因为没有任务表(这是我的想法)!哇,非常感谢您,先生,您对这里其他解决方案的 cmets 非常有帮助!
  • 调用第三次迁移,如2017_10_15_024000_add_foreign_key_to_messages_table.php,它将在您显示的两次迁移后执行。
  • 您是否从第一次迁移中删除了$table->foreign('task_id')...
  • 在这种情况下,错误应该与您发布的错误不同。
  • 您使用的是Schema::create 而不是Schema::table。请看我回答中的代码,它使用Schema::table
【解决方案2】:

一对一的关系将数据库表中的一行链接到另一个表中的一个(并且只有一个)行。

onDelete('cascade') 用于在多对多关系中的两个表之间存在中间表(也称为数据透视表)时。对于一对一的关系,您不需要这个,因为到消息表的链接只存在于任务表的行中(并且正在被删除)。

为任务表迁移试试这个:

public function up()
{
    Schema::create('tasks', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('message_id')->unsigned()->nullable();
        $table->foreign('message_id')->references('id')->on('messages');
        $table->timestamps();

    });
}

【讨论】:

  • 感谢Kerrin,但是如果App\Message 行被删除,我怎样才能让它删除相应的App\Task 行?反之亦然?
  • onDelete('cascade') 与多对多或一对一关系无关。这是关于级联删除的好读物techonthenet.com/sql_server/foreign_keys/foreign_delete.php
  • 是的,我只是回到这里来纠正这个问题。如上所述,外键到位后,onDelete('cascade') 将按预期工作。
  • @kerrin 它仍然不起作用,因为还没有 messages 表。并且只有在2017_10_15_021803_create_messages_table.php执行后才会创建这个表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多