PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Nazwa tabeli jako parametr funkcji PostgreSQL

Można to jeszcze bardziej uprościć i ulepszyć:

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

Zadzwoń z nazwą kwalifikowaną według schematu (patrz poniżej):

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

Lub:

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

Główne punkty

Użyj OUT parametr uprościć funkcję. Możesz bezpośrednio wybrać do niego wynik dynamicznego SQL i gotowe. Nie ma potrzeby stosowania dodatkowych zmiennych i kodu.

EXISTS robi dokładnie to, co chcesz. Otrzymujesz true jeśli wiersz istnieje lub false Inaczej. Można to zrobić na różne sposoby, EXISTS jest zazwyczaj najbardziej wydajny.

Wygląda na to, że potrzebujesz liczby całkowitej z powrotem, więc przesyłam boolean wynik z EXISTS na integer , co daje dokładnie to, co miałeś. Zwróciłbym boolean zamiast tego.

Używam identyfikatora obiektu typu regclass jako typ wejściowy dla _tbl . To robi wszystko quote_ident(_tbl) lub format('%I', _tbl) zrobiłoby to, ale lepiej, ponieważ:

  • .. zapobiega wstrzyknięciu SQL tak samo dobrze.

  • .. zawodzi natychmiast i bardziej wdzięcznie, jeśli nazwa tabeli jest nieprawidłowa / nie istnieje / jest niewidoczna dla bieżącego użytkownika. (regclass parametr ma zastosowanie tylko do istniejących tabele.)

  • .. działa z nazwami tabel kwalifikowanych schematem, gdzie zwykły quote_ident(_tbl) lub format(%I) zawiedzie, ponieważ nie mogą rozwiązać niejasności. Musiałbyś osobno przekazywać i zmieniać nazwy schematów i tabel.

Działa tylko w przypadku istniejących stoły, oczywiście.

Nadal używam format() , ponieważ upraszcza składnię (i demonstruje, jak jest używana), ale z %s zamiast %I . Zazwyczaj zapytania są bardziej złożone, więc format() pomaga bardziej. W przypadku prostego przykładu równie dobrze moglibyśmy po prostu połączyć:

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

Nie ma potrzeby kwalifikowania tabeli id kolumna, podczas gdy w FROM znajduje się tylko jedna tabela lista. W tym przykładzie nie ma dwuznaczności. (Dynamiczne) polecenia SQL wewnątrz EXECUTE mieć oddzielny zakres , zmienne funkcji lub parametry nie są tam widoczne - w przeciwieństwie do zwykłych poleceń SQL w treści funkcji.

Oto dlaczego zawsze Poprawnie escape użytkownika dla dynamicznego SQL:

db<>graj tutaj demonstracja wstrzykiwania SQL
Stary sqlfiddle



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSql :tablica Json do wierszy przy użyciu łączenia bocznego

  2. Jak działa funkcja Setseed() w PostgreSQL

  3. Mówienie użytkownikom, aby sami się rozwidlili

  4. PostgreSQL unnest() z numerem elementu

  5. nieprawidłowa sekwencja bajtów do kodowania UTF8