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

plpgsql - używanie dynamicznej nazwy tabeli w deklaracji deklaracji

Ważne jest, aby zrozumieć podstawową naturę tych pięciu różnych rodzajów danych/symbolów :

1. 'my_tbl'

Literał ciągu znaków unknown wpisz . Gdy jest używany w SQL (osadzony w kodzie plpgsql lub nie), jest przypisywany do typu pochodzącego z kontekstu . Jeśli nie można określić typu, może być wymagane jawne rzutowanie. Na przykład:'my_tbl'::text .

2. 'my_tbl'::text

Ten sam literał ciągu znaków rzutowany na wpisz text . Może zawierać nazwę tabeli, ale tak naprawdę to tylko tekst.

3. 'my_tbl'::regclass

identyfikator obiektu (OID) dla zarejestrowanej klasy . Jest wyświetlany i może być wprowadzony jako ciąg znaków reprezentujący poprawną nazwę obiektu ('my_tbl' ). Dane wyjściowe są automatycznie kwalifikowane według schematu ('my_schema.my_tbl' ) i / lub w cudzysłowie ('"mY_TbL"' ), jeśli byłoby to niejednoznaczne lub niezgodne z prawem. Może to być zwykły stół , sekwencja , wyświetl , widok zmaterializowany , typ złożony itp. Szczegóły w tej powiązanej odpowiedzi:

4. my_tbl_var my_tbl (skrót od my_tbl_var my_tbl%ROWTYPE )

W DECLARE sekcja bloku kodu plpgsql, która jest deklaracją zmiennej z dobrze znanym typ wiersza (alias typu kompozytowego). Typ musi być zarejestrowany w tabeli systemowej pg_class (tak samo jak z regclass zmienny). Nie jest to OID obiektu, do którego się odwołuje, ale jego rzeczywisty typ wiersza. my_tbl_var i my_tbl oba są identyfikatorami tutaj i nie można go sparametryzować. Możesz także rzutować dowolny wiersz lub rekord bezpośrednio:(123, 'foo')::my_tbl

5. my_tbl_var record

W DECLARE sekcja bloku kodu plpgsql, która jest deklaracją anonimowego nagraj . Zasadniczo symbol zastępczy dla jeszcze nieznanego typu wiersza / o jeszcze niezdefiniowanej strukturze. Może być używany w większości miejsc, w których można użyć typu wiersza. Ale nie możesz uzyskać z niego dostępu do pól przed przypisaniem zmiennej rekordu.

Myliłeś się 1. , 3. i 4. i rozwiązał go za pomocą 5. zamiast tego.
Ale więcej dzieje się źle tutaj:

  • Wybierasz całą tabelę, ale zmienna wierszowa (rekordowa) może zawierać tylko jeden wiersz na raz. Tak więc tylko pierwszy jest przypisywany i zwracany. Chociaż nie ma ORDER BY klauzuli, wynik jest dowolny i może ulec zmianie w dowolnym momencie. Zła pułapka.

  • Ponieważ używasz teraz record typu, musisz upewnić się, że został przypisany, zanim będziesz mógł uruchomić testy na jego polach, w przeciwnym razie otrzymasz wyjątki dla pustych tabel. W Twoim przypadku sprawdź record_var IS NULL prawie wykonuje tę samą pracę. Ale istnieje przypadek narożny dla wierszy z NULL we wszystkich polach:wtedy record_var IS NULL ocenia się jako prawda. Jeszcze trudniejsze dla testu IS NOT NULL . Szczegóły tutaj:

    Dodałem demo do skrzypce SQL poniżej.

  • Funkcja zwraca pojedynczy skalar (boolean ) wartość. Użyj:

    RETURN false;
    

    Zamiast:

    RETURN QUERY SELECT false;

Funkcja

CREATE FUNCTION check_valid(_tbl regclass)
  RETURNS bool AS
$func$
DECLARE
   r record;
   _row_ct int;
BEGIN
   EXECUTE '
   SELECT is_valid, hit_count, hit_limit
   FROM  ' || _tbl || '
   ORDER  <whatever>
   LIMIT  1'            -- replace <whatever> with your sort criteria
   INTO r;              -- only needed columns

   GET DIAGNOSTICS _row_ct = ROW_COUNT;

   IF _row_ct = 0 THEN  -- necessary, because r may not be assigned
      RETURN false;
   ELSIF NOT r.is_valid OR r.hit_count > r.hit_limit THEN
      RETURN false;
   END IF;

   RETURN true;
END
$func$  LANGUAGE plpgsql;

Skrzypce SQL (z dwoma wariantami funkcji i demonstracją wiersza IS NULL).

Główne punkty

  • Użyj GET DIAGNOSTICS aby dowiedzieć się, czy w instrukcji dynamicznej znaleziono jakieś wiersze za pomocą EXECUTE .

  • IF wyrażenie może być uproszczone.

  • Parametr jest typu regclass , a nie tylko nazwę tabeli. Nie użyłbym mylącej nazwy „tablename” dla tego parametru. To tylko zwiększa twoje początkowe zamieszanie. Nazywam to _tbl zamiast tego.

Jeśli chcesz także zwrócić zestaw zmiennych typów wierszy:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres brakujący błąd wpisu klauzuli FROM w zapytaniu z klauzulą ​​WITH

  2. Maksymalna wartość rzędowa (z n kolumn) - Eleganckie podejście

  3. Użytkownicy aplikacji a zabezpieczenia na poziomie wiersza

  4. Powiąż parametr tablicy z natywnym zapytaniem

  5. PostgreSQL, niestandardowe agregaty