CakePHP:如何有效地实施唯一的连接表记录

时间:2013-11-21 21:03:11

标签: php cakephp join cakephp-2.0 has-and-belongs-to-many

我正在使用CakePHP 2.x而且我经常遇到我想要将记录添加到连接表的情况,但我想确保相同的“连接”记录不存在。

具体而言,这是一个基本的例子......

模特:学生有和贝伦到多个课程 型号:课程有和贝伦到多个学生 加入Table = courses_students并有字段“student_id”和“course_id”

假设我有一个学生的表格,我希望与课程相关联。表单向控制器提交了一堆student_id。在我添加新记录之前,我需要确保记录不存在(因为您不能两次注册相同的课程)。这是事情变得混乱的地方......

选项1:我有时为连接表中每个(可能)预先存在的记录构建一个deleteAll(),该记录包含当前的course_id和任何提交的user_id。这是有效的,但缺点是它会删除可能存储在其他字段中的任何预先存在的数据,例如日期等。

选项2:我有时会遍历每个提交的记录,并为每个(可能)预先存在的记录执行find()。这允许我保留现有记录,但对数据库进行了大量额外查询。

这是我通常处理这种情况的两种方式,但我怀疑有更好的方法。它是什么?

1 个答案:

答案 0 :(得分:0)

您可以使用REPLACE INTO。例如:

REPLACE INTO courses_students (course_id, student_id, when)
  VALUES (1, 2, 12345678)

哪个会用新值覆盖列when。我确信在纯SQL中有一种方法可以不这样做:http://dev.mysql.com/doc/refman/5.0/en/replace.html

也不确定它在CakePHP中的作用。他们的DBAL可能有数据库合并的帮助。

(MySQL不支持MERGE INTO .. WHEN MATCHED,所以你必须先做SELECT然后INSERT。)

(顺便说一下:选项2效率不高,因为你已经为course_id + student_id创建了一个复合的唯一键。SELECT将非常快。)< / p>

修改
如果您正确地索引列,SELECT非常非常快且便宜。表courses_students应该在(course_id, student_id)上有一个PK。如果您担心查询的数量,可以在1个查询中执行所有SELECT:

:ids from input
SELECT course_id, student_id FROM courses_students WHERE course_id IN (:ids) AND student_id IN (:ids)

然后将它们映射到一个assoc可访问的数组:

array(course_id => array(student_id => TRUE))

然后循环输入(POST?)并过滤现有记录:

if ( !isset($map[$course_id][$student_id]) ) {
  // INSERT HERE
}

总共count(INPUT) + 1个查询。

但所有这些都是很多代码。您可以循环查询每条记录。我保证它很便宜。