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

Funkce Postgres vytvoří, ale nespustí se

Měl jsem podobnou situaci - funkce s širokým seznamem parametrů. S takzvanými pojmenovanými parametry , nemusíte respektovat pořadí parametrů. Kód je delší, ale (doufám) čitelnější a robustnější.

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$

Tuto funkci lze volat pomocí pojmenovaných parametrů zápis:

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

Upozornění:Když použiji špatný typ – Postgres hlásí zprávu:

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.

Zpráva je platná, ale není čistá. Je to náklad na podporu přetížení funkcí. Existuje další trik, jak rozdělit dlouhý seznam parametrů a jak tyto problémy pohodlněji najít.

Postgres podporuje vlastní typy. Můžete jej použít:

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

můžete napsat funkce konstruktoru:

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$

Vytvoření tohoto systému vyžaduje určitou práci a je praktické pouze pro systémy s dlouhou životností. Na druhé straně to snižuje náklady na budoucí údržbu.

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$

Nyní je možných více zápisů (kombinací zápisů):

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

(1 row)

Konstruktor pomáhá s lokalizací chyb:

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. Smazat všechny záznamy kromě nejnovějšího?

  2. získat seznam čísel mezi dvěma sloupci

  3. Proč se auto_increment id nezvyšuje jeden po druhém, jak to nastavit?

  4. Automaticky poskytnout jedinečné ID v databázi