sql >> Database >  >> RDS >> PostgreSQL

Postgres-functie maakt aan, maar wordt niet uitgevoerd

Ik had een vergelijkbare situatie - functie met brede parameterlijst. Met zogenaamde benoemde parameters , hoeft u geen volgorde van parameters te respecteren. Code is langer, maar (hoop ik) leesbaarder en robuuster.

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$

Deze functie kan worden aangeroepen met benoemde parameters notatie:

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

Let op:als ik het verkeerde type gebruik - Postgres rapporteert bericht:

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.

Het bericht is geldig, maar het is niet schoon. Het is een kost van ondersteuning voor functieoverbelasting. Er is een andere truc, hoe een lange parameterlijst te verdelen en hoe deze problemen gemakkelijker te vinden.

Postgres ondersteunt aangepaste typen. Je kunt het gebruiken:

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

je kunt een constructorfunctie schrijven:

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$

Het maken van dit systeem vereist wat werk en het is alleen praktisch voor systemen met een lange levensduur. Aan de tweede kant verlaagt het de kosten voor toekomstig onderhoud.

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$

Nu zijn meer notaties (combinatie van notaties) mogelijk:

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

(1 row)

Constructors helpt bij foutlokalisatie:

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. Converteer MySQL's PUNT naar tekst in PHP

  2. Hoe toon ik afbeeldingen uit de MySQL-database in een JavaScript-afbeeldingsschuifregelaar?

  3. Kan geen verbinding maken met localhost, maar wel met computernaam in SQL Server 2008

  4. Oracle groeperen op slechts ÉÉN kolom