Trong mã plpgsql, SELECT
mà không có mục tiêu sẽ gây ra lỗi. Nhưng rõ ràng bạn không không muốn SELECT INTO
, bạn chỉ muốn đặt trạng thái của FOUND
. Bạn sẽ sử dụng PERFORM
cho điều đó.
- SELECT tăng ngoại lệ trong hàm PL / pgSQL
Tốt hơn, nhưng , sử dụng IF EXISTS ...
. Hãy xem xét việc viết lại hàm này của bạn:
CREATE OR REPLACE FUNCTION "insertarNuevoArticulo"( nombrearticulo text, descripcion text, idtipo int, idfamilia bigint, artstock int, minstock int, maxstock int, idmarca bigint, precio real, marcastock int)
RETURNS boolean
LANGUAGE plpgsql AS
$func$
DECLARE
_id_articulo "Articulo"."idArticulo"%TYPE;
BEGIN
SELECT a."idArticulo" INTO _id_articulo
FROM "Articulo" a
WHERE a."Nombre" = $1 AND a."idTipo" = $3 AND a."idFamilia" = $4;
IF NOT FOUND THEN
INSERT INTO "Articulo"("Nombre", "Descripcion", "idTipo", "idFamilia", "Stock", "MinStock", "MaxStock")
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING "Articulo"."idArticulo" INTO _id_articulo;
END IF;
IF EXISTS (SELECT FROM "ArticuloMarca" a
WHERE a."idArticulo" = _id_articulo AND a."idMarca" = $8) THEN
RETURN false;
ELSE
INSERT INTO "ArticuloMarca"("idArticulo", "idMarca", "PrecioReferencial", "Stock")
VALUES (_id_articulo, $8, $9, $10);
RETURN true;
END IF;
END
$func$;
Giới thiệu về EXISTS
:
- Kiểm tra PL / pgSQL nếu một hàng tồn tại
Điểm chính khác :
- Sử dụng
RETURNING
mệnh đề củaINSERT
thay vì mộtSELECT
bổ sung .
Postgres 9.5+
Trong Postgres 9.5 trở lên, hãy sử dụng INSERT ... ON CONFLICT DO NOTHING
(a.k.a. "UPSERT") để thay thế.
Bạn sẽ có UNIQUE
ràng buộc về "Articulo"("Nombre", "idTipo", "idFamilia")
và "ArticuloMarca"("idArticulo", "idMarca")
và sau đó:
CREATE OR REPLACE FUNCTION insert_new_articulo( nombrearticulo text, descripcion text, idtipo int, idfamilia bigint, artstock int, minstock int, maxstock int, idmarca bigint, precio real, marcastock int)
RETURNS boolean
LANGUAGE plpgsql AS
$func$
DECLARE
_id_articulo "Articulo"."idArticulo"%TYPE;
BEGIN
LOOP
SELECT "idArticulo" INTO _id_articulo
FROM "Articulo"
WHERE "Nombre" = $1 AND "idTipo" = $3 AND "idFamilia" = $4;
EXIT WHEN FOUND;
INSERT INTO "Articulo"("Nombre", "Descripcion", "idTipo", "idFamilia", "Stock", "MinStock", "MaxStock")
VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (tag) DO NOTHING
RETURNING "idArticulo" INTO _id_articulo;
EXIT WHEN FOUND;
END LOOP;
LOOP
INSERT INTO "ArticuloMarca"("idArticulo", "idMarca", "PrecioReferencial", "Stock")
VALUES (_id_articulo, $8, $9, $10)
ON CONFLICT ("idArticulo", "idMarca") DO NOTHING;
IF FOUND THEN
RETURN true;
END IF;
IF EXISTS (SELECT FROM "ArticuloMarca"
WHERE "idArticulo" = _id_articulo AND "idMarca" = $8) THEN
RETURN false;
END IF;
END LOOP;
END
$func$;
Điều này nhanh hơn, đơn giản hơn và đáng tin cậy hơn. Các vòng lặp được thêm vào loại trừ mọi điều kiện đua còn lại với việc ghi đồng thời (trong khi hầu như không thêm bất kỳ chi phí nào). Không cần ghi đồng thời, bạn có thể đơn giản hóa. Giải thích chi tiết:
- CHỌN hoặc CHÈN trong một hàm có nguy cơ gặp phải các điều kiện về chủng tộc không?
- Cách sử dụng RETURNING với ON CONFLICT trong PostgreSQL?
Ngoài ra:sử dụng các số nhận dạng hợp pháp, viết thường để tránh tất cả các dấu ngoặc kép ồn ào.