sql >> Databasteknik >  >> RDS >> PostgreSQL

Returnera flera fält som en post i PostgreSQL med PL/pgSQL

Använd inte CREATE TYPE för att returnera ett polymorft resultat. Använd och missbruka RECORD-typen istället. Kolla in det:

CREATE FUNCTION test_ret(a TEXT, b TEXT) RETURNS RECORD AS $$
DECLARE 
  ret RECORD;
BEGIN
  -- Arbitrary expression to change the first parameter
  IF LENGTH(a) < LENGTH(b) THEN
      SELECT TRUE, a || b, 'a shorter than b' INTO ret;
  ELSE
      SELECT FALSE, b || a INTO ret;
  END IF;
RETURN ret;
END;$$ LANGUAGE plpgsql;

Var uppmärksam på att den valfritt kan returnera två eller tre kolumner beroende på indata.

test=> SELECT test_ret('foo','barbaz');
             test_ret             
----------------------------------
 (t,foobarbaz,"a shorter than b")
(1 row)

test=> SELECT test_ret('barbaz','foo');
             test_ret             
----------------------------------
 (f,foobarbaz)
(1 row)

Detta orsakar förödelse på kod, så använd ett konsekvent antal kolumner, men det är löjligt praktiskt för att returnera valfria felmeddelanden med den första parametern som returnerar framgången för operationen. Omskrivet med ett konsekvent antal kolumner:

CREATE FUNCTION test_ret(a TEXT, b TEXT) RETURNS RECORD AS $$
DECLARE 
  ret RECORD;
BEGIN
  -- Note the CASTING being done for the 2nd and 3rd elements of the RECORD
  IF LENGTH(a) < LENGTH(b) THEN
      ret := (TRUE, (a || b)::TEXT, 'a shorter than b'::TEXT);
  ELSE
      ret := (FALSE, (b || a)::TEXT, NULL::TEXT);
   END IF;
RETURN ret;
END;$$ LANGUAGE plpgsql;

Nästan till episk hethet:

test=> SELECT test_ret('foobar','bar');
   test_ret    
----------------
 (f,barfoobar,)
(1 row)

test=> SELECT test_ret('foo','barbaz');
             test_ret             
----------------------------------
 (t,foobarbaz,"a shorter than b")
(1 row)

Men hur delar du upp det i flera rader så att ditt valda ORM-lager kan konvertera värdena till ditt språks ursprungliga datatyper? Hettan:

test=> SELECT a, b, c FROM test_ret('foo','barbaz') AS (a BOOL, b TEXT, c TEXT);
 a |     b     |        c         
---+-----------+------------------
 t | foobarbaz | a shorter than b
(1 row)

test=> SELECT a, b, c FROM test_ret('foobar','bar') AS (a BOOL, b TEXT, c TEXT);
 a |     b     | c 
---+-----------+---
 f | barfoobar | 
(1 row)

Detta är en av de coolaste och mest underanvända funktionerna i PostgreSQL. Sprid gärna ordet.



  1. PostgreSQL GROUP_CONCAT() Ekvivalent

  2. Hur använder man scheman i Django?

  3. Lär dig hur du säkerhetskopierar din MySQL-databas

  4. Kapacitetsplanering med hjälp av resultatdata