sql >> Databáze >  >> RDS >> PostgreSQL

SELECT nebo PERFORM ve funkci PL/pgSQL

V kódu plpgsql SELECT bez cíle spustí chybu. Ale to evidentně ne chcete SELECT INTO , chcete pouze nastavit stav FOUND . Použili byste PERFORM za to.

  • SELECT vyvolá výjimku ve funkci PL/pgSQL

Ještě lepší , použijte IF EXISTS ... . Zvažte tento přepis vaší funkce:

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$;

O EXISTS :

  • PL/pgSQL kontroluje, zda řádek existuje

Další hlavní bod :

  • Použijte RETURNING klauzule INSERT místo dalšího SELECT .

Postgres 9.5+

V Postgres 9.5 nebo novějším použijte INSERT ... ON CONFLICT DO NOTHING (také znám jako „UPSERT“).
Měli byste UNIQUE omezení na "Articulo"("Nombre", "idTipo", "idFamilia") a "ArticuloMarca"("idArticulo", "idMarca") a poté:

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$;

Je to rychlejší, jednodušší a spolehlivější. Přidané smyčky vylučují jakékoli zbývající podmínky závodu se souběžnými zápisy (a přitom nepřidávají téměř žádné náklady). Bez souběžných zápisů můžete zjednodušit. Podrobné vysvětlení:

  • Je SELECT nebo INSERT ve funkci náchylný k závodům?
  • Jak používat RETURNING s ON CONFLICT v PostgreSQL?

Stranou:používejte legální identifikátory s malými písmeny, abyste se vyhnuli všem hlučným dvojitým uvozovkám.



  1. MariaDB JSON_REMOVE() Vysvětleno

  2. Oracle Indexy a typy indexů v oracle s příkladem

  3. Jak spravovat uživatele a autentizaci v MySQL

  4. Únik z jednoduché uvozovky v PHP při vkládání do MySQL