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

Fungsi Postgres membuat tetapi tidak mengeksekusi

Saya memiliki situasi serupa - fungsi dengan daftar parameter lebar. Dengan apa yang disebut parameter bernama , Anda tidak perlu mengikuti urutan parameter. Kode lebih panjang, tetapi (saya harap) lebih mudah dibaca dan lebih kuat.

CREATE TABLE tab(name text, surname text, address text, city text, zip text);

CREATE OR REPLACE FUNCTION public.fx(name text, surname text,
                                     address text, city text, zip text)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
  INSERT INTO tab(name, surname, address, city, zip)
    VALUES(fx.name, fx.surname, fx.address, fx.city, fx.zip);
  -- ... some other logic
END;
$function$

Fungsi ini dapat dipanggil dengan parameter bernama notasi:

SELECT fx(name := 'Pavel', surname := 'Stehule',
          address := 'Skalice 12', city := 'Benesov', zip := '12');

Perhatian:Saat saya menggunakan jenis yang salah - Pesan laporan Postgres:

postgres=#   SELECT fx(name := 'Pavel', surname := 'Stehule',
              address := 'Skalice 12', city := 'Benesov', zip := 12);
ERROR:  function fx(name := unknown, surname := unknown, address := unknown, city := unknown, zip := integer) does not exist
LINE 1: SELECT fx(name := 'Pavel', surname := 'Stehule',
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

Pesannya valid, tetapi tidak bersih. Ini adalah biaya dukungan fungsi yang berlebihan. Ada trik lain, bagaimana membagi daftar parameter yang panjang, dan bagaimana menemukan masalah ini dengan lebih nyaman.

Postgres mendukung jenis khusus. Anda dapat menggunakannya:

CREATE TYPE person_type AS (name text, surname text);
CREATE TYPE address_type AS (address text, city text, zip text);

anda dapat menulis fungsi konstruktor:

CREATE OR REPLACE FUNCTION public._person_type(name text, surname text)
RETURNS person_type
LANGUAGE plpgsql
AS $function$
DECLARE r person_type;
BEGIN
  r.name = name;
  r.surname = surname;
  RETURN r;
END;
$function$

CREATE OR REPLACE FUNCTION public._address_type(address text, city text, zip text)
RETURNS address_type
LANGUAGE plpgsql
AS $function$ DECLARE r address_type;
BEGIN
  r.address = address;
  r.city = city;
  r.zip = zip;
  RETURN r;
END;
$function$

Membuat sistem ini membutuhkan beberapa pekerjaan dan praktis hanya untuk sistem yang berumur panjang. Di sisi lain, ini mengurangi biaya untuk pekerjaan pemeliharaan di masa mendatang.

CREATE OR REPLACE FUNCTION public.fx(p person_type, a address_type)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
  INSERT INTO tab(name, surname, address, city, zip)
    VALUES(p.name, p.surname, a.address, a.city, a.zip);
   -- ... some other logic
END;
$function$

Sekarang, lebih banyak notasi (kombinasi notasi) dimungkinkan:

postgres=# SELECT fx(_person_type('Pavel','Stehule'),
postgres(#           _address_type('Skalice 12','Benesov', '25601'));
 fx 
----

(1 row)

Konstruktor membantu dengan pelokalan kesalahan:

postgres=# SELECT fx(_person_type('Pavel','Stehule'),
          _address_type('Skalice 12','Benesov', 25601));
ERROR:  function _address_type(unknown, unknown, integer) does not exist
LINE 2:           _address_type('Skalice 12','Benesov', 25601));
                  ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.


  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 9.1 - mengakses tabel melalui fungsi

  2. Menambahkan (mendorong) dan menghapus dari array JSON di PostgreSQL 9.5+

  3. ubah kolom dari waktu dengan zona waktu ke cap waktu

  4. pelanggaran isolasi transaksi yang jelas di postgresql

  5. Datetime default dengan Ecto &Elixir