PostgreSQL 重复键值违反唯一约束,同时在冲突中使用时在插入时不执行任何操作
PostgreSQL duplicate key value violates unique constraint while using on conflict do nothing on insert
Table def:
CREATE SEQUENCE IF NOT EXISTS lazy_product_stock_id_seq;
CREATE TABLE "public"."lazy_product_stock" (
"id" int4 NOT NULL DEFAULT nextval('lazy_product_stock_id_seq'::regclass),
"product_id" int4,
"hold" int4 DEFAULT 0,
"quantity" int4 DEFAULT 0,
"warehouse_id" int4,
PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX lazy_product_stock_pkey ON public.lazy_product_stock USING btree (id)
CREATE INDEX lazy_product_stock_product_id_idx ON public.lazy_product_stock USING btree (product_id)
CREATE INDEX lazy_product_stock_warehouse_id_idx ON public.lazy_product_stock USING btree (warehouse_id)
CREATE UNIQUE INDEX CONCURRENTLY "lazy_product_stock_comb_idx2" ON "public"."lazy_product_stock" USING BTREE ("product_id","warehouse_id");
我有一个将新行插入数据库的函数:
CREATE OR REPLACE FUNCTION sp_lazystock_i_f(_product_id int4, site_id int4) RETURNS VOID AS $$
declare
warehouse record;
BEGIN
FOR warehouse IN select id from warehouse where siteid = site_id LOOP
insert into lazy_product_stock (product_id, warehouse_id) VALUES (_product_id, warehouse.id) ON CONFLICT (product_id,warehouse_id) DO NOTHING;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
它失败了
duplicate key value violates unique constraint "lazy_product_stock_comb_idx2"
指数
CREATE UNIQUE INDEX CONCURRENTLY "lazy_product_stock_comb_idx2" ON "public"."lazy_product_stock" USING BTREE ("product_id","warehouse_id");
尽管 运行 相关插入本身具有重复值,但没有问题。
insert into lazy_product_stock (product_id, warehouse_id) VALUES (123, 1234) ON CONFLICT (product_id,warehouse_id) DO NOTHING;
Query 1 OK: INSERT 0 0, 0 rows affected
我不明白函数和单个语句之间的区别是什么?
这也没有问题:
do $$
declare
warehouse record;
begin
FOR warehouse IN select id from warehouse where siteid = 123 LOOP
insert into lazy_product_stock (product_id, warehouse_id) VALUES (12345, warehouse.id) ON CONFLICT (product_id,warehouse_id) DO NOTHING;
END LOOP;
end; $$ LANGUAGE plpgsql;
与
同样的错误
insert into lazy_product_stock (product_id, warehouse_id)
select _product_id, warehouse.id
from warehouse where siteid = site_id
on conflict (product_id, warehouse_id) do nothing;
我正在使用 Postgresql 12.3
为什么要为此使用循环?怎么样:
insert into lazy_product_stock (product_id, warehouse_id)
select _product_id, w.id
from warehouse where siteid = site_id
on conflict (product_id, warehouse_id) do nothing;
不指定目标是否有效?
insert into lazy_product_stock (product_id, warehouse_id)
select _product_id, warehouse.id
from warehouse
where siteid = site_id
on conflict do nothing;
do nothing
是唯一一个不需要指定目标的冲突操作,这使得这里的解决方法成为可能。
似乎我有 2 个这样的函数触发了导致问题的相同逻辑。谢谢大家的帮助。
Table def:
CREATE SEQUENCE IF NOT EXISTS lazy_product_stock_id_seq;
CREATE TABLE "public"."lazy_product_stock" (
"id" int4 NOT NULL DEFAULT nextval('lazy_product_stock_id_seq'::regclass),
"product_id" int4,
"hold" int4 DEFAULT 0,
"quantity" int4 DEFAULT 0,
"warehouse_id" int4,
PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX lazy_product_stock_pkey ON public.lazy_product_stock USING btree (id)
CREATE INDEX lazy_product_stock_product_id_idx ON public.lazy_product_stock USING btree (product_id)
CREATE INDEX lazy_product_stock_warehouse_id_idx ON public.lazy_product_stock USING btree (warehouse_id)
CREATE UNIQUE INDEX CONCURRENTLY "lazy_product_stock_comb_idx2" ON "public"."lazy_product_stock" USING BTREE ("product_id","warehouse_id");
我有一个将新行插入数据库的函数:
CREATE OR REPLACE FUNCTION sp_lazystock_i_f(_product_id int4, site_id int4) RETURNS VOID AS $$
declare
warehouse record;
BEGIN
FOR warehouse IN select id from warehouse where siteid = site_id LOOP
insert into lazy_product_stock (product_id, warehouse_id) VALUES (_product_id, warehouse.id) ON CONFLICT (product_id,warehouse_id) DO NOTHING;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
它失败了
duplicate key value violates unique constraint "lazy_product_stock_comb_idx2"
指数
CREATE UNIQUE INDEX CONCURRENTLY "lazy_product_stock_comb_idx2" ON "public"."lazy_product_stock" USING BTREE ("product_id","warehouse_id");
尽管 运行 相关插入本身具有重复值,但没有问题。
insert into lazy_product_stock (product_id, warehouse_id) VALUES (123, 1234) ON CONFLICT (product_id,warehouse_id) DO NOTHING;
Query 1 OK: INSERT 0 0, 0 rows affected
我不明白函数和单个语句之间的区别是什么?
这也没有问题:
do $$
declare
warehouse record;
begin
FOR warehouse IN select id from warehouse where siteid = 123 LOOP
insert into lazy_product_stock (product_id, warehouse_id) VALUES (12345, warehouse.id) ON CONFLICT (product_id,warehouse_id) DO NOTHING;
END LOOP;
end; $$ LANGUAGE plpgsql;
与
同样的错误insert into lazy_product_stock (product_id, warehouse_id)
select _product_id, warehouse.id
from warehouse where siteid = site_id
on conflict (product_id, warehouse_id) do nothing;
我正在使用 Postgresql 12.3
为什么要为此使用循环?怎么样:
insert into lazy_product_stock (product_id, warehouse_id)
select _product_id, w.id
from warehouse where siteid = site_id
on conflict (product_id, warehouse_id) do nothing;
不指定目标是否有效?
insert into lazy_product_stock (product_id, warehouse_id)
select _product_id, warehouse.id
from warehouse
where siteid = site_id
on conflict do nothing;
do nothing
是唯一一个不需要指定目标的冲突操作,这使得这里的解决方法成为可能。
似乎我有 2 个这样的函数触发了导致问题的相同逻辑。谢谢大家的帮助。