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

Restituisce le righe SETOF dalla funzione PostgreSQL

Funzione di sanificazione

Quello che hai attualmente può essere semplificato/igienizzato in:

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$;

Hai solo bisogno di ulteriori istanze di BEGIN ... END nel corpo della funzione per avviare blocchi di codice separati con il proprio ambito, che è raramente necessario.

L'operatore di concatenazione SQL standard è || . + è un'aggiunta "creativa" del tuo ex fornitore.

Non utilizzare identificatori di maiuscole e minuscole CaMeL a meno che non vengano virgolette. Meglio non usarli affatto Vedi:

  • I nomi delle colonne di PostgreSQL fanno distinzione tra maiuscole e minuscole?

varchar(4000) è inoltre adattato a una specifica limitazione di SQL Server. Non ha un significato specifico in Postgres. Usa solo varchar(4000) se hai effettivamente bisogno di un limite di 4000 caratteri. Userei semplicemente text - tranne per il fatto che non abbiamo bisogno di alcuna variabile per niente qui, dopo aver semplificato la funzione.

Se non hai utilizzato format() , tuttavia, consulta il manuale qui.

Tipo di reso

Ora, per la tua vera domanda:il tipo restituito per una query dinamica può essere complicato poiché SQL richiede che venga dichiarato al più tardi al momento della chiamata. Se hai una tabella o una vista o un tipo composto nel tuo database che corrisponde già all'elenco delle definizioni delle colonne, puoi semplicemente usarlo:

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

Altrimenti, scrivi l'elenco delle definizioni delle colonne senza con (il più semplice) RETURNS TABLE :

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

Se stai scrivendo la riga mentre procedi, puoi restituire record anonimi:

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

Ma poi devi fornire un elenco di definizioni di colonna con ogni chiamata, quindi non lo uso quasi mai.

Non userei SELECT * iniziare con. Utilizza un elenco definitivo di colonne da restituire e dichiara il tuo tipo di reso di conseguenza:

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$;

Per query completamente dinamiche, per cominciare, considera la creazione della query nel tuo client, invece di utilizzare una funzione.

Devi prima capire le basi:

  • Refactoring di una funzione PL/pgSQL per restituire l'output di varie query SELECT
  • PL/pgSQL nel manuale di Postgres

Poi ci sono opzioni più avanzate con tipi polimorfici, che ti permettono di passare il tipo restituito al momento della chiamata. Altro nell'ultimo capitolo di:

  • Refactoring di una funzione PL/pgSQL per restituire l'output di varie query SELECT