【问题标题】:Conditional INSERT INTO statement in postgrespostgres 中的条件 INSERT INTO 语句
【发布时间】:2013-03-20 13:30:34
【问题描述】:

我正在为模拟航空公司预订数据库编写预订程序,我真正想做的是这样的:

IF EXISTS (SELECT * FROM LeadCustomer 
    WHERE FirstName = 'John' AND Surname = 'Smith') 
THEN
   INSERT INTO LeadCustomer (Firstname, Surname, BillingAddress, email) 
   VALUES ('John', 'Smith', '6 Brewery close,
            Buxton, Norfolk', 'cmp.testing@example.com');

但是 Postgres 不支持 IF 不加载 PL/pgSQL 扩展的语句。我想知道是否有办法做到这一点,或者在这一步中是否需要进行一些用户交互?

【问题讨论】:

  • 为什么不直接加载 PL/pgSQL 扩展呢?
  • @MattBall:在实验室计算机上安装 postgres。使用该扩展不在规范中。

标签: database postgresql conditional-statements sql-insert


【解决方案1】:

该特定命令可以这样完成:

insert into LeadCustomer (Firstname, Surname, BillingAddress, email)
select 
    'John', 'Smith', 
    '6 Brewery close, Buxton, Norfolk', 'cmp.testing@example.com'
where not exists (
    select 1 from leadcustomer where firstname = 'John' and surname = 'Smith'
);

它将插入选择语句的结果,select 只会在该客户不存在时返回一行。

【讨论】:

  • 我认为这里有一场(非常小的)比赛? select子查询运行,返回0行,另一个线程发生insert,然后发生LeadCustomer insert?
  • @Kevin 将引发主键异常,应用程序将决定做什么。
  • 我很困惑,这个问题在任何地方都没有提到主键。如果 (firstname, surname) 上有一个主键,为什么不先尝试插入?
  • @Kevin 我会先尝试插入。问题只是关于语法。
  • 有没有办法像这样插入多行?
【解决方案2】:

自 9.5 版本起包含 pgsql upsert,使用 INSERT ... ON CONFLICT DO UPDATE ...

下面的答案不再相关。几年后发布了 Postgres 9.5,并提供了更好的解决方案。

如果不添加新功能,Postgres 没有“upsert”功能。
您需要做的是运行选择查询并查看是否有匹配的行。如果你这样做,然后插入它。

我知道你并不完全想要一个 upsert,但它几乎是一样的。

【讨论】:

  • 即使发生冲突(尝试插入时),这也会继续增加自动递增的 id
  • “检查结果,有条件地插入”容易出现竞争条件:如果你有两个线程同时在做,你可以得到两个插入。
  • @CharlesDuffy 不在事务中(如果选择更新,则不在事务中)
猜你喜欢
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多