如果条目不存在,则使用PostgreSQL进行多个插入
如果条目不存在,我想将数据插入多个表中 在我的例子中,我有一个餐厅表、一个位置表、一个如果条目不存在,则使用PostgreSQL进行多个插入,sql,postgresql,common-table-expression,sql-insert,Sql,Postgresql,Common Table Expression,Sql Insert,如果条目不存在,我想将数据插入多个表中 在我的例子中,我有一个餐厅表、一个位置表、一个foodtype表和一些助手表,如restaurant\u location、和restaurant\u foodtype。现在,我想插入一个新的餐馆条目,如果条目不存在,则包含位置和foodtype信息 比如: IF NOT (select 1 from restaurant where name='restaurantname') THEN INSERT INTO restaurant(x,y) VALU
foodtype
表和一些助手表,如restaurant\u location
、和restaurant\u foodtype
。现在,我想插入一个新的餐馆条目,如果条目不存在,则包含位置和foodtype信息
比如:
IF NOT (select 1 from restaurant where name='restaurantname') THEN
INSERT INTO restaurant(x,y) VALUES (valuex,valuey);
INSERT INTO restaurant_location(rest_id,..) VALUES (rest_id,..);
INSERT INTO restaurant_foodtype(rest_id,..) VALUES (rest_id,..);
...
END IF
如何使用简单SQL实现这一点?我只是在头脑中写下了这一点,但如果必须使用简单SQL,这应该是我的想法
insert into
restaurant(x, y)
values
select valuex, valuey
from dual
where
not exists(
select 1 from restaurant where name = 'restaurantname')
编辑: 同样,我无法解析它,但您可能可以使用WITH子句:
with validation as(
select 1 from restaurant where name = 'restaurantname'
)
insert into
restaurant(x, y)
values
(
select value1x, value1y
from dual
where
validation.v = 1),
(
select value2x, value2y
from dual
where
validation.v = 1)
在Postgres9.1或更高版本中您可以使用它来实现快速、安全、简单和优雅:
WITH x AS (
INSERT INTO restaurant(name, x, y)
SELECT 'restaurantname', valuex, valuey
WHERE NOT EXISTS (SELECT 1 FROM restaurant WHERE name = 'restaurantname')
RETURNING rest_id -- returns auto-generated id (from sequence)
)
, y AS (
INSERT INTO restaurant_location(rest_id, ...)
SELECT rest_id, ...
FROM x -- only produces rows after a successful INSERT
)
--- more chained INSERTs here?
INSERT INTO restaurant_foodtype(rest_id, ...)
SELECT rest_id, ...
FROM x;
只有在未找到“restaurantname”时,才会执行第一次插入。如果多个查询在同一实例中尝试相同的查询,则存在一个极小的竞争条件。如果您对restaurant.name
有UNIQUE
约束(就像您应该从描述中判断的那样),最糟糕的情况是,在并发查询中,只有第一个查询会成功,而其他查询返回时会出现唯一的违规(不执行任何操作)。然而,你可能永远也看不到这一点,因为这不太可能发生
RETURNING
子句返回自动生成的rest\u id
——我假设rest\u id
是一个串行列
以下INSERT
查询仅在第一个查询成功时生成行
用一个简单的插入来完成本系列
使用PostgreSQL 8.1,我将编写一个plpgsql函数来实现同样的功能。
但是,实际上,您最好升级到。这对于一条insert语句非常有效。但我有多个。仅仅将WHERE NOT EXISTS添加到每一个INSERT中是不起作用的,因为在第一次INSERT之后,条目应该存在。如果第一行餐厅不存在,那么您将插入一行。那家餐馆的身份证号码可以通过电话查询。您不需要检查相关插入是否存在id号;外键约束保证它不可能存在,除非您的数据库设计被严重破坏。没有“简单”的SQL查询插入到多个表中。但是它很容易在plpgsql的过程代码中完成,这看起来很像问题中的伪代码。如果你因为某种原因不能使用它,欢迎提供更多关于上下文的信息。8.1已经很长时间不受支持了。您现在应该升级了,真的。@DanielVérité:好吧,因为Postgres 9.1可以使用“简单”的SQL语句,使用数据修改CTE来完成升级。我发布了一个示例。这基本上就是我在要求版本时的想法;)这是“快速、安全、简单、优雅”吗?我只是在一个项目中使用postGreSQL,我想知道这是否真的是执行此注释操作的最简单方法。如果将其包装在一个返回复合数据类型的函数中,则如果存在,将返回一个空行(而不是无行)。为什么?