plpgsql कोड में, SELECT
लक्ष्य के बिना एक त्रुटि ट्रिगर करता है। लेकिन आप स्पष्ट रूप से नहीं करते हैं चाहते हैं SELECT INTO
, आप बस FOUND
. की स्थिति सेट करना चाहते हैं . आप PERFORM
. का प्रयोग करेंगे उसके लिए।
- PL/pgSQL फ़ंक्शन में चयन अपवाद उठाता है
बेहतर, अभी तक , IF EXISTS ...
. का उपयोग करें . अपने फ़ंक्शन के इस पुनर्लेखन पर विचार करें:
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$;
EXISTS
के बारे में :
- PL/pgSQL जाँच कर रहा है कि कोई पंक्ति मौजूद है या नहीं
अन्य प्रमुख बिंदु :
RETURNING
का उपयोग करेंINSERT
. का खंड अतिरिक्तSELECT
. के बजाय स्टेटमेंट ।
पोस्टग्रेज 9.5+
Postgres 9.5 या बाद के संस्करण में INSERT ... ON CONFLICT DO NOTHING
का उपयोग करें (a.k.a. "UPSERT") इसके बजाय।
आपके पास UNIQUE
होगा "Articulo"("Nombre", "idTipo", "idFamilia")
पर बाधाएं और "ArticuloMarca"("idArticulo", "idMarca")
और फिर:
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$;
यह तेज़, सरल और अधिक विश्वसनीय है। जोड़े गए लूप समवर्ती लेखन के साथ किसी भी शेष दौड़ की स्थिति को रद्द करते हैं (जबकि शायद ही कोई लागत जोड़ते हैं)। समवर्ती लेखन के बिना, आप सरल बना सकते हैं। विस्तृत विवरण:
- क्या किसी ऐसे फंक्शन में SELECT या INSERT है जो दौड़ की स्थिति से ग्रस्त है?
- PostgreSQL में ON CONFLICT के साथ RETURNING का उपयोग कैसे करें?
इसके अलावा:सभी शोर-शराबे वाले दोहरे उद्धरणों से बचने के लिए कानूनी, लोअर-केस आइडेंटिफ़ायर का उपयोग करें।