如何以编程方式'upsert',在postgres中使用php

时间:2017-02-20 11:06:12

标签: php postgresql

Upsert在PG中是一个很棒的新东西(我们最近更新了数据库以使用它),现在我们正在尝试在PHP中编写upsert适配器,以便使用起来很简单。

如果我们想要upsert,我们应该怎么做:

INSERT INTO {$this->_name} AS t ({$insertCols}) VALUES ({$insertVals})
              ON CONFLICT {$onConflict} DO UPDATE
                SET {$updateVals}
                WHERE {$updateWhere}

我们可以将它简化为更简单的功能,这在代码中更方便:

ModelTable()->getInstance()->getAdapter->upsert($data, $onConflict, $where);
//e.g.
ModelTable()->getInstance()->getAdapter->upsert(['name=>'Denis', 'age'=>36], '(name)', "name = 'Denis'");

在这种情况下,使用更方便,但问题是 - 我们必须知道限制列名称(名称)或限制名称本身将其放在$ onConflict变量中。上面示例中的变量'(name)'

如果要为该表添加另一个限制,或重命名旧表,则应更新与该表一起使用的整个php代码以添加新限制。

理想适配器应该看起来像常规更新适配器:

ModelTable()->getInstance()->getAdapter->upsert(['name=>'Denis', 'age'=>36], "name = 'Denis'");

因此,如果存在name = Denis的行,则会更新,如果不存在,则应该创建。

所以问题是 - 如何在php中创建可以这样工作的adaper?我们知道应该更新哪一行的列名,因此应该可以构造ON CONFLICT ... DO UPDATE句子。我想对任何冲突进行更新,与

相同
try {
 ...insert
} catch (Exception $e) {
 ...update
}

我们现在正在使用。

谢谢。

1 个答案:

答案 0 :(得分:0)

你想要实现upsert的方式就像捕捉\Exception一样意味着«如果插入不起作用,我会尝试更新。»承认这是一个真正缺乏控制权域名。您可能希望在与主键冲突时更新行,但在与示例相同的表中的唯一字段冲突时拒绝这些行。

冲突的原因属于模型,这些是明确实现为约束的业务规则。只有模型层知道它拒绝插入的原因并改为更新行。因此,无论域定义如何,它都不能是可以在所有表​​上调用的通用upsert命令。

这意味着这是ModelTable实例,它知道记录与现有数据冲突的原因,就像它知道表结构一样(我猜你的例子)。