sql >> Database >  >> RDS >> PostgreSQL

plpgsql-functie:rijen retourneren uit een weergave die is gemaakt op basis van een willekeurige tabel

Het zou als volgt kunnen werken:

CREATE OR REPLACE FUNCTION tt_query(orig_name regclass, data_tt timestamp)
  RETURNS SETOF record AS
$func$
BEGIN

EXECUTE 'CREATE OR REPLACE TEMP VIEW tmp as 
select * 
from  '
|| orig_name 
|| ' where trigger_changed >'
|| quote_literal(data_tt)
|| ' ORDER BY trigger_changed DESC';

-- other work on view tmp

-- return the rows of view temp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;
  • Let op het gebruik van de object-identificatietype regclass om automatisch SQL-injectie te voorkomen.

  • Gebruik niet de verouderde syntaxis var ALIAS for $1 als het niet hoeft. Declareer in plaats daarvan parameternamen.

  • Ik zou het trefwoord temp niet gebruiken als identifier, zelfs als dat is toegestaan. tmp gebruiken in plaats daarvan.

  • Gebruik RETURN QUERY om een ​​reeks records te retourneren. Dit kan zelfs een statische oproep zijn zonder EXECUTE . U retourneert echter anonieme records en Postgres eist een kolomdefinitielijst bij elke oproep:

SELECT * FROM tt_query('tbl_name', '2014-02-15 12:00')
AS f(col1 int, col2 text, ...);

Dit is nogal onpraktisch.

Betere oplossingen

Als je weet het retourtype (zelfs als tabelnamen veranderen, kan de lijst met kolommen dezelfde typen delen), declareer het bij het maken. Overweeg deze gerelateerde vraag:
PostgreSQL:FOUT:42601:een kolomdefinitielijst is vereist voor functies die "record" retourneren

Als het retourtype varieert met de opgegeven tabelnaam is er nog steeds een veel betere oplossing. Aangezien u een weergave maakt met SELECT * FROM tbl , kunt u het bekende type tabel zelf gebruiken als polymorf parameter:

CREATE OR REPLACE FUNCTION tt_query(orig_name anyelement, data_tt timestamp)
  RETURNS SETOF anyelement AS
$func$
BEGIN

EXECUTE format('CREATE OR REPLACE TEMP VIEW tmp AS
   SELECT * FROM  %s
   WHERE  trigger_changed > %L
   ORDER  BY trigger_changed DESC'
  ,pg_typeof(orig_name)
  ,data_tt);

-- other work on view tmp

-- return the rows of view tmp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;

Vereenvoudigde oproep:

SELECT * FROM tt_query(NULL::tbl_name, '2014-02-15 12:00');

Gebruikt ook format() voor veilige en eenvoudige aaneenschakeling van strings.

Meer details in dit gerelateerde antwoord:
Refactor een PL/pgSQL-functie om de uitvoer van verschillende SELECT-query's te retourneren




  1. Hoe de UCASE()-functie werkt in MySQL

  2. Kan een opgeslagen procedure werken met twee verschillende databases? Wat dacht je van twee servers?

  3. MAAK een tabel met datumtype en gebruik de standaardwaarde als CURRENT_DATE op MySQL

  4. MySQL/PDO kapt de gegevens af