sql >> Databasteknik >  >> RDS >> PostgreSQL

Deklarera tupelstrukturen för en post i PL/pgSQL

Du blandar syntaxen för att returnera SETOF värden med syntax för att returnera en enstaka rad eller ett värde.

-- En relaterad fråga är - hur returnerar jag den enskilda posten 'r' från

När du deklarerar en funktion med RETURNS TABLE , du måste använda RETURN NEXT i kroppen för att returnera en rad (eller skalärt värde). Och om du vill använda en record variabel med att den måste matcha returtypen. Se kodexemplen längre ner.

Returnera ett enstaka värde eller rad

Om du bara vill returnera en enda rad, finns det inget behov för en post av odefinierad typ. @Kevin har redan visat två sätt. Jag lägger till en förenklad version med OUT parametrar:

CREATE OR REPLACE FUNCTION my_func(OUT a integer, OUT b text)
   AS
$func$
BEGIN
   a := ...;
   b := ...;
END
$func$ LANGUAGE plpgsql;

Du behöver inte ens lägga till RETURN; i funktionskroppen, värdet på den deklarerade OUT parametrar kommer att returneras automatiskt i slutet av funktionen - NULL för någon parameter som inte har tilldelats.
Och du behöver inte deklarera RETURNS RECORD eftersom det redan är tydligt från OUT parametrar.

Returnera en uppsättning rader

Om du faktiskt vill returnera flera rader (inklusive möjligheten för 0 eller 1 rad), kan du definiera returtypen som RETURNS ...

  • SETOF some_type , där some_type kan vara vilken registrerad skalär eller sammansatt typ som helst.

  • TABLE (col1 type1, col2 type2) - en ad-hoc definition av radtyp.

  • SETOF record plus OUT parametrar för att definiera kolumnnamn och -typer.
    100 % motsvarar RETURNS TABLE .

  • SETOF record utan närmare definition. Men då är de returnerade raderna odefinierade och du måste inkludera en kolumndefinitionslista med varje anrop (se exempel).

Manualen om posttypen:

Postvariabler liknar variabler av radtyp, men de har ingen fördefinierad struktur. De tar på sig den faktiska radstrukturen för raden de tilldelas under ett SELECT- eller FOR-kommando.

Det finns mer, läs manualen.

Du kan använda en postvariabel utan att tilldela en definierad typ, du kan även returnera sådana odefinierade poster:

CREATE OR REPLACE FUNCTION my_func()
  RETURNS SETOF record AS
$func$
DECLARE
    r record;
BEGIN
    r := (1::int, 'foo'::text); RETURN NEXT r; -- works with undefined record
    r := (2::int, 'bar'::text); RETURN NEXT r;
END
$func$ LANGUAGE plpgsql;

Ring:

SELECT * FROM my_func() AS x(a int, b text);

Men det här är mycket otympligt eftersom du måste tillhandahålla kolumndefinitionslistan med varje samtal. Det kan i allmänhet ersättas med något mer elegant:

  • Om du känner till typen när funktionen skapades, deklarera den omedelbart (RETURNS TABLE eller vänner).

CREATE OR REPLACE FUNCTION my_func()
  RETURNS SETOF tbl_or_type AS
$func$
DECLARE
    r tbl_or_type;
BEGIN
    SELECT INTO tbl_or_type  * FROM tbl WHERE id = 10;
    RETURN NEXT r;  -- type matches

    SELECT INTO tbl_or_type  * FROM tbl WHERE id = 12;
    RETURN NEXT r;

    -- Or simpler:
    RETURN QUERY
    SELECT * FROM tbl WHERE id = 14;
END
$func$ LANGUAGE plpgsql;
  • Om du känner till typen vid tidpunkten för funktionsanropet , det finns mer eleganta sätt att använda polymorfa typer:
    Refaktorera en PL/pgSQL-funktion för att returnera utdata från olika SELECT-frågor

Din fråga är otydlig om vad du behöver exakt.



  1. Distribuera en Hybrid Cloud MySQL-databas med ClusterControl

  2. Oracle Index och typer av index i Oracle med exempel

  3. Hur skapar man främmande nyckel i Oracle SQL Developer?

  4. Parametrisera en SQL IN-sats