sql >> Database >  >> RDS >> PostgreSQL

Retourneer SETOF-rijen van de PostgreSQL-functie

Sanitiseerfunctie

Wat u momenteel heeft, kan worden vereenvoudigd/opgeschoond tot:

CREATE OR REPLACE FUNCTION func_a (username text = '', databaseobject text = '')
  RETURNS ????
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY EXECUTE
   format ('SELECT * FROM %s v1 LEFT JOIN %I v2 USING (id)'
         , CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
         , databaseobject);
END
$func$;

Je hebt alleen extra exemplaren van BEGIN ... END . nodig in de functietekst om afzonderlijke codeblokken met hun eigen bereik te starten, wat zelden nodig is.

De standaard SQL-aaneenschakelingsoperator is || . + is een "creatieve" toevoeging van uw voormalige leverancier.

Gebruik geen CaMeL-case-ID's, tenzij u ze dubbel aanhaalt. Gebruik ze het beste helemaal niet Zie:

  • Zijn PostgreSQL-kolomnamen hoofdlettergevoelig?

varchar(4000) is ook afgestemd op een specifieke beperking van SQL Server. Het heeft geen specifieke betekenis in Postgres. Gebruik alleen varchar(4000) als u daadwerkelijk een limiet van 4000 tekens nodig heeft. Ik zou gewoon text gebruiken - behalve dat we helemaal geen variabelen nodig hebben hier, na het vereenvoudigen van de functie.

Als je format() not niet hebt gebruikt , maar, raadpleeg hier de handleiding.

Retourtype

Nu, voor uw eigenlijke vraag:het retourtype voor een dynamische query kan lastig zijn, omdat SQL vereist dat dit uiterlijk bij de oproep wordt gedeclareerd. Als u een tabel of weergave of samengesteld type in uw database heeft die al overeenkomt met de kolomdefinitielijst, kunt u die gewoon gebruiken:

CREATE FUNCTION foo()
  RETURNS SETOF my_view AS
...

Anders, spel de kolomdefinitielijst met out met (eenvoudigste) RETURNS TABLE :

CREATE FUNCTION foo()
  RETURNS TABLE (col1 int, col2 text, ...) AS
...

Als u de rij typt terwijl u bezig bent, kunt u anonieme records retourneren:

CREATE FUNCTION foo()
  RETURNS SETOF record AS
...

Maar dan moet je bij elke oproep een kolomdefinitielijst opgeven, dus die gebruik ik bijna nooit.

Ik zou SELECT * niet gebruiken beginnen met. Gebruik een definitieve lijst met kolommen om te retourneren en geef uw retourtype dienovereenkomstig aan:

CREATE OR REPLACE FUNCTION func_a(username text = '', databaseobject text = '')
  RETURNS TABLE(col1 int, col2 text, col3 date)
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY EXECUTE
   format ($f$SELECT v1.col1, v1.col2, v2.col3
              FROM %s v1 LEFT JOIN %I v2 USING (id)$f$
         , CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
         , databaseobject);
END
$func$;

Overweeg voor volledig dynamische zoekopdrachten om de zoekopdracht in uw client te bouwen, in plaats van een functie te gebruiken.

U moet eerst de basis begrijpen:

  • Refactor een PL/pgSQL-functie om de uitvoer van verschillende SELECT-query's te retourneren
  • PL/pgSQL in de Postgres-handleiding

Dan zijn er meer geavanceerde opties met polymorfe typen, waarmee u het retourtype tijdens het gesprek kunt doorgeven. Meer in het laatste hoofdstuk van:

  • Refactor een PL/pgSQL-functie om de uitvoer van verschillende SELECT-query's te retourneren



  1. SYSDATE-functie in Oracle

  2. mysql2 gem gecompileerd voor verkeerde mysql-clientbibliotheek

  3. Hoe een PostgreSQL-database migreren naar een SQLServer-database?

  4. Fix Error Msg 4151 "Het type van het eerste argument voor NULLIF kan niet de NULL-constante zijn omdat het type van het eerste argument bekend moet zijn" in SQL Server