sql >> Database teknologi >  >> RDS >> PostgreSQL

Postgres-funktionen opretter, men udføres ikke

Jeg havde en lignende situation - funktion med bred parameterliste. Med såkaldte navngivne parametre , behøver du ikke respektere en rækkefølge af parametre. Koden er længere, men (håber jeg) mere læsbar og mere robust.

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$

Denne funktion kan kaldes med navngivne parametre notation:

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

Bemærk:Når jeg bruger forkert type - Postgres rapporterer besked:

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.

Meddelelsen er gyldig, men den er ikke ren. Det er en omkostning ved funktionsoverbelastningsstøtte. Der er et andet trick, hvordan man deler lang parameterliste, og hvordan man finder disse problemer mere komfortabelt.

Postgres understøtter brugerdefinerede typer. Du kan bruge det:

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

du kan skrive en konstruktørfunktioner:

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$

At skabe dette system kræver noget arbejde, og det er kun praktisk for systemer med lang levetid. På anden side reducerer det en omkostning for fremtidigt vedligeholdelsesarbejde.

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 er flere notationer (kombination af notationer) mulige:

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

(1 row)

Konstruktører hjælper med fejllokalisering:

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. find antal åbne forbindelser på databasen

  2. Returliste<String> ved hjælp af Spring jdbc fra Oracle-lagret procedure med brugerdefineret objekt

  3. Problem med kompleks mysql-forespørgsel ved hjælp af forberedt erklæring

  4. VÆLG distinkte værdier for flere rækker med samme id