在 Laravel 的数据透视表中添加 id 列有啥好处?

Posted

技术标签:

【中文标题】在 Laravel 的数据透视表中添加 id 列有啥好处?【英文标题】:Any advantages of adding an id column to a pivot table in Laravel?在 Laravel 的数据透视表中添加 id 列有什么好处? 【发布时间】:2016-03-20 09:41:38 【问题描述】:

在 Laravel(我使用的是 5.1 版)的数据透视表(多对多关系)中有一个 id 列有什么好处吗?

有身份证

        $table->increments('id');

        $table->integer('appointment_id')->unsigned();
        $table->foreign('appointment_id')->references('id')->on('appointments')->onDelete('cascade');

        $table->integer('client_id')->unsigned();
        $table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');

        $table->timestamps();

没有身份证

        $table->integer('appointment_id')->unsigned();
        $table->foreign('appointment_id')->references('id')->on('appointments')->onDelete('cascade');

        $table->integer('client_id')->unsigned();
        $table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');

        $table->timestamps();

【问题讨论】:

如果您没有主键,$object->delete() 是否有效? (我认为是为increments 自动创建的,但我的经验主要是 Laravel 4...) 是的,它对我有用,它会删除我的数据透视表中的所有内容、父行和关系,但我使用 delete Cascade。 这与在标准数据透视表上拥有一个自动递增的 id 列相同:拥有一个列并没有什么坏处,但它们最终是多余的,因为你是 (最有可能)永远不会直接查询数据透视表。示例SELECT * FROM pivot_table WHERE id = 5; 除非您知道您特别想要该行,否则真的没有意义。 在 Laravel 中同步不是很有用吗?例如$user->roles()->sync([1, 2, 3]); laravel.com/docs/5.1/… 可能会更容易删除,但我想不会太多。我注意到,对于您定义的模型关系,我与数据透视表本身没有太多交互......除了删除。 【参考方案1】:

一般来说,答案是否定的,前提是 Laravel 的 Eloquent 模型正在管理这种关系。

但是,如果您需要从 Eloquent 模型之外访问表(例如,从另一个应用程序或在遥远的将来,当您重写应用程序以使用下一个大型框架时),ID 将派上用场。

【讨论】:

谢谢,有道理。 旧,但是,在数据透视表中具有唯一 ID 还可以让您直接从 sql 客户端/sql 工作台编辑表条目。【参考方案2】:

迟到的答案,但您可以删除自动增量id,并将您的外键用作数据透视表的复合主键:

$table->integer('appointment_id')->unsigned();
$table->foreign('appointment_id')->
    references('id')->on('appointments')->onDelete('cascade');

$table->integer('client_id')->unsigned();
$table->foreign('client_id')->
    references('id')->on('clients')->onDelete('cascade');

// add the following instruction

$table->primary(['appointment_id', 'client_id']);

使用 Laravel 5.6 进行测试,这不会破坏 Eloquent 的管理,同时直接在您的数据库结构中确保关联的唯一性。

More about creating indexes...

【讨论】:

什么?我一直听说 Laravel 不支持,也永远不会支持复合键 @nowox 来自doc :“您甚至可以将列数组传递给索引方法以创建复合(或复合)索引”。所以我想它是受支持的:) 那我猜你可以用复合索引创建表,但是你cannot use in Eloquent【参考方案3】:

在数据透视表上添加 id 作为主键时要小心,因为它会“破坏”外键对唯一性的任何验证,这意味着您可能有多个具有相同外键对的记录。

【讨论】:

嗯,你是对的。我想,唯一的解决方法是在两个外键对 $table->unique(array('appointment_id', 'client_id')); 上添加唯一索引 我不认为这应该是一个问题,因为id 列将是AUTO_INCREMENT 是的,如果你有一个自动增量 id 字段,那么你需要做一个唯一的对约束。【参考方案4】:

如果您要设置 mysql 组复制 - 您必须在每个表上都有主键。

17.7.1 组复制要求 要用于组复制的服务器实例必须满足以下要求。

基础设施 InnoDB 存储引擎。数据必须存储在 InnoDB 事务存储引擎。交易被执行 乐观地,然后在提交时检查是否存在冲突。如果 有冲突,以保持整个过程的一致性 组,一些事务被回滚。这意味着一个 需要事务存储引擎。此外,InnoDB 提供 一些额外的功能,可以实现更好的管理和 处理与 Group Replication 一起操作时的冲突。

主键。该组要复制的每个表都必须 具有已定义的主键或等效的主键,其中 等效项是非空唯一键。这样的键是必需的 表中每一行的唯一标识符,使系统能够 通过准确识别哪些事务来确定哪些事务冲突 每个事务已修改的行。

IPv4 网络。 MySQL Group 使用的组通信引擎 复制仅支持 IPv4。因此,组复制需要 IPv4 网络基础设施。

网络性能。组复制旨在部署在 服务器实例非常接近每个集群的集群环境 其他,并且受网络延迟和网络的影响 带宽。

【讨论】:

"...必须有一个已定义的主键或 PRIMARY KEY EQUIVALENT,其中等效项是非空唯一键" 在数据透视表上添加 id 会浪费大量时间和空间,而不是提到一致性的大问题,因为您可以在两个实体之间建立重复的关系。因此,除非您计划使这些数据透视记录成为实际实体,或者实际上是您业务中的实体,否则拥有额外的 id 字段确实是一个丑陋的设计 当我读到它似乎并不表示需要增量 id 字段时。它只是说:它需要一个主键。据我所知,数据透视表中的 2 个值应该是主键。他们在原始帖子中的问题(我认为)是您是否应该像大多数其他表一样放置一个增量 id 字段。

以上是关于在 Laravel 的数据透视表中添加 id 列有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 在带有分页的数据透视表中搜索

Laravel 在数据透视表中为克隆字段的一个关系 ID 插入多行

如何在 laravel 中使用数据透视表中的 3 个关系创建关系?

如何使用 laravel 删除数据透视表中的单行

在另一个表 Laravel 中查找具有数据透视表中所有 id 的记录

Laravel 根据数据透视表从表中获取标题