PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PILIH atau PERFORM dalam fungsi PL/pgSQL

Dalam kode plpgsql, SELECT tanpa target memicu kesalahan. Tapi Anda jelas tidak ingin SELECT INTO , Anda hanya ingin mengatur status FOUND . Anda akan menggunakan PERFORM untuk itu.

  • SELECT memunculkan pengecualian dalam fungsi PL/pgSQL

Lebih baik, namun , gunakan IF EXISTS ... . Pertimbangkan penulisan ulang fungsi Anda ini:

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

Tentang EXISTS :

  • PL/pgSQL memeriksa apakah ada baris

Poin utama lainnya :

  • Gunakan RETURNING klausa dari INSERT pernyataan alih-alih SELECT . tambahan .

Postgres 9.5+

Di Postgres 9.5 atau yang lebih baru gunakan INSERT ... ON CONFLICT DO NOTHING (alias "UPSERT") sebagai gantinya.
Anda akan memiliki UNIQUE batasan pada "Articulo"("Nombre", "idTipo", "idFamilia") dan "ArticuloMarca"("idArticulo", "idMarca") lalu:

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

Ini lebih cepat, lebih sederhana, dan lebih dapat diandalkan. Loop yang ditambahkan mengesampingkan kondisi balapan yang tersisa dengan penulisan bersamaan (sambil menambahkan hampir tidak ada biaya). Tanpa penulisan bersamaan, Anda dapat menyederhanakan. Penjelasan detail:

  • Apakah SELECT atau INSERT dalam fungsi rentan terhadap kondisi balapan?
  • Bagaimana cara menggunakan RETURNING dengan ON CONFLICT di PostgreSQL?

Selain:gunakan pengidentifikasi huruf kecil yang legal untuk menghindari semua tanda kutip ganda yang berisik.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mengubah tipe kolom menjadi string yang lebih panjang di Rails

  2. Menggunakan pg_dump untuk hanya mendapatkan pernyataan penyisipan dari satu tabel dalam database

  3. Jalankan file .sql PostgreSQL menggunakan argumen baris perintah

  4. Apa yang baru di PostgreSQL 13?

  5. Bagaimana cara membuat daftar indeks yang dibuat untuk tabel di postgres