Upsert
是 PG 中的一个很棒的新东西(我们最近更新了数据库以使用它),现在我们正在尝试用 PHP 编写 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 中创建可以那样工作的适配器?我们知道应该更新哪一行的列名,所以应该可以构造ON CONFLICT ... DO UPDATE
语句。我想更新任何冲突,就像
try {
...insert
} catch (Exception $e) {
...update
}
我们现在正在使用。
谢谢。
最佳答案
你想要实现 upsert
的方式,比如捕获 \Exception
意味着 «如果插入不管什么原因都不起作用,我会尝试更新。»承认这是真正缺乏对域的控制。例如,您可能希望在与主键冲突时更新行,但在与同一表中的唯一字段冲突时拒绝行。
冲突的原因属于模型,这些是明确实现为约束的业务规则。只有模型层知道为什么它会拒绝插入并改为更新行。因此,无论域定义如何,它都不能是您可以在所有表上调用的通用 upsert 命令。
这意味着这是 ModelTable
实例,它知道为什么记录会与现有数据冲突,就像它知道表结构一样(正如我从您的示例中猜测的那样)。
关于php - 如何以编程方式在 postgres 中使用 php 'Upsert',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42342907/