我有一个comment
表和一个comment_edit
表,以及olddb_edit
。简化后,相关表如下所示:
CREATE TABLE `olddb_edit` (
edit_id INT NOT NULL,
edit_time INT NOT NULL,
edit_text TEXT NOT NULL,
PRIMARY KEY (edit_id, edit_time)
) ENGINE=InnoDB;
现在我想将内容从另一个数据库迁移到编辑表中,但是跳过一些表行,例如测试注释。我为此使用CakePHP(实际上是Phinx)。
通常,这足够:
$skippable = array(
12345, 23456, 34567, 45678,
);
$rows = $this->getQueryBuilder()
->select('*')
->from('olddb_comment')
->where(array(
'comment_id NOT IN' => $skippable,
))
->execute()
->fetchAll('assoc')
;
但是简单的NOT IN
子句显然不适用于复合主键。
我在想,$skippable
数组应如下所示:
$skippable = array(
array('id' => 707969, 'time' => 1434462225),
array('id' => 707969, 'time' => 1434462463),
array('id' => 707969, 'time' => 1434462551),
);
然后,我将通过for循环或其他方式运行where子句。但老实说,我什至不知道如何在香草MySQL中做到这一点。
可能已经在SO上发布了一个解决方案,但是我找不到任何解决方案(除了特定于其他应用程序的解决方案)。我猜该算法不是我的朋友。
[没关系,我在提出问题时自己想出了办法。无论如何,我都会将答案发布给有类似问题的其他人。
首先,香草MySQL。如果您分解NOT IN
(imo),它会像您想的那样直观:
SELECT * FROM olddb_edit WHERE
NOT (
(edit_id = 707969) AND (edit_time = 1434461454)
OR (edit_id = 707969) AND (edit_time = 1434461503)
OR (edit_id = 707969) AND (edit_time = 1434461925)
);
并且使用CakePHP / Phinx查询生成器,您使用匿名函数,for循环和not-or构造:
$qb = $this->getQueryBuilder()
->select('*')
->from('olddb_edit')
->where(array(
'edit_some_other_optional_condition = 1',
))
// also skip skippables.
->where(function($exp) use ($skippable) {
$ORed = array();
foreach ($skippable as $edit) {
array_push($ORed, array(
'edit_id' => $edit['id'],
'edit_time' => $edit['time'],
));
}
return $exp->not($exp->or_($ORed));
})
;