如果条目不存在,我想将数据插入到多个表中。
在我的情况下,我有一个餐馆餐桌,一个位置表,一个foodtype
表和一些辅助表,如restaurant_location
和restaurant_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执行此操作?
答案 0 :(得分:7)
在Postgres 9.1或更高版本中,您可以使用data-modifying CTEs来实现快速,安全,简单和优雅:
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'时才会执行第一个INSERT
。如果多个查询在同一个实例中尝试相同,则存在超小的竞争条件。如果你对UNIQUE
有一个restaurant.name
约束(就像你应该从你的描述中判断一样),可能发生的最糟糕的情况是,在同意的查询中,只有第一个会成功,而其他人会以唯一的违规行为返回(什么也不做)。但是,你很可能永远不会看到这一点,因为它不太可能发生。
RETURNING
子句返回自动生成的rest_id
- 我认为rest_id
是一个串行列。
以下INSERT
个查询仅在第一个查询成功时生成行。
使用普通INSERT
完成系列。
使用PostgreSQL 8.1我会编写一个plpgsql函数来实现相同的目标 但是,实际上,您最好升级到current version。
答案 1 :(得分:1)
我只是把它写在了我的头脑中,但这应该是想法,如果你必须用简单的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)