sql >> Databáze >  >> RDS >> PostgreSQL

Název tabulky jako parametr funkce PostgreSQL

To lze dále zjednodušit a zlepšit:

CREATE OR REPLACE FUNCTION some_f(_tbl regclass, OUT result integer)
    LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('SELECT (EXISTS (SELECT FROM %s WHERE id = 1))::int', _tbl)
   INTO result;
END
$func$;

Volání s názvem kvalifikovaným pro schéma (viz níže):

SELECT some_f('myschema.mytable');  -- would fail with quote_ident()

Nebo:

SELECT some_f('"my very uncommon table name"');

Hlavní body

Použijte OUT parametra pro zjednodušení funkce. Můžete do něj přímo vybrat výsledek dynamického SQL a hotovo. Není potřeba dalších proměnných a kódu.

EXISTS dělá přesně to, co chcete. Získáte true pokud řádek existuje nebo false v opačném případě. Existují různé způsoby, jak to udělat, EXISTS je obvykle nejúčinnější.

Zdá se, že chcete celé číslo zpět, takže jsem přenesl boolean výsledek z EXISTS na integer , která dává přesně to, co jste měli. Vrátil bych boolean místo toho.

Používám typ identifikátoru objektu regclass jako typ vstupu pro _tbl . To dělá vše quote_ident(_tbl) nebo format('%I', _tbl) by to šlo, ale lépe, protože:

  • .. zabraňuje vkládání SQL stejně dobře.

  • .. selže okamžitě a elegantněji, pokud je název tabulky neplatný / neexistuje / je pro aktuálního uživatele neviditelný. (regclass parametr je použitelný pouze pro existující tabulky.)

  • .. funguje s názvy tabulek kvalifikovaných pro schéma, kde je prostý quote_ident(_tbl) nebo format(%I) by selhaly, protože nedokážou vyřešit nejednoznačnost. Názvy schémat a tabulek byste museli předat a escapovat samostatně.

Funguje pouze pro existující tabulky, samozřejmě.

Stále používám format() , protože to zjednodušuje syntaxi (a ukazuje, jak se používá), ale s %s místo %I . Dotazy jsou obvykle složitější, takže format() pomáhá více. Pro jednoduchý příklad bychom také mohli zřetězit:

EXECUTE 'SELECT (EXISTS (SELECT FROM ' || _tbl || ' WHERE id = 1))::int'

id není třeba kvalifikovat podle tabulky zatímco v FROM je pouze jedna tabulka seznam. V tomto příkladu není možná žádná nejednoznačnost. (Dynamické) příkazy SQL uvnitř EXECUTE mají samostatný rozsah , funkční proměnné nebo parametry tam nejsou vidět - na rozdíl od jednoduchých příkazů SQL v těle funkce.

Zde je důvod, proč vždy správně escape uživatelského vstupu pro dynamické SQL:

db<>zde hrajte demonstrace SQL injection
Starý sqlfiddle



  1. Vytvořte entitu místnosti pro tabulku, která má pole s datovým typem LONG ve Sqlite

  2. Jak vytvořit uživatele s oprávněními superuživatele v PostgreSQL

  3. Oracle ODP.Net With Entity Framework 6 – poskytovatel kompatibilní s databází Entity Framework nebyl nalezen

  4. Přehled streamovací replikace pro TimescaleDB