MySQL:您如何查询复合主键?具体来说,是NOT IN查询吗?

问题描述 投票:0回答:1

我有一个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 cakephp composite-primary-key notin phinx
1个回答
0
投票

[没关系,我在提出问题时自己想出了办法。无论如何,我都会将答案发布给有类似问题的其他人。


首先,香草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));
    })
;
© www.soinside.com 2019 - 2024. All rights reserved.