PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

SELECT или PERFORM във функция PL/pgSQL

В plpgsql код, SELECT без цел предизвиква грешка. Но вие очевидно не искате SELECT INTO , просто искате да зададете състоянието на FOUND . Ще използвате PERFORM за това.

  • SELECT повдига изключение във функцията 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 .

Postgres 9.5+

В Postgres 9.5 или по-нова версия използвайте INSERT ... ON CONFLICT DO NOTHING (известен още като "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$;

Това е по-бързо, по-лесно и по-надеждно. Добавените цикли изключват всички останали условия на състезание с едновременни записи (като същевременно добавят почти никакви разходи). Без едновременни записи можете да опростите. Подробно обяснение:

  • Изберете или INSERT във функция предразположени ли са условия на състезание?
  • Как да използвам RETURNING с ON CONFLICT в PostgreSQL?

Настрана:използвайте легални идентификатори с малки букви, за да избегнете всички шумни двойни кавички.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да конфигурирам postgresql за първи път?

  2. SSL за възли за PostgreSQL връзка

  3. Върнете се към readline версия 6.x в Homebrew, за да коригирате Postgresql?

  4. PostgreSQL ПОКАЖЕ ТАБЛИЦИ Еквивалент (psql)

  5. Актуализиране на JLabel чрез SetIcon от тип данни bytea в postgres