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