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

plpgsql - použití názvu dynamické tabulky v příkazu deklarovat

Je důležité porozumět základní povaze těchto pěti různých druhů dat / symbolů :

1. 'my_tbl'

Řetězcový literál unknown typu . Při použití v SQL (vložené do kódu plpgsql nebo ne), je vynuceno na typ odvozený z kontextu . Pokud nelze typ určit, může být vyžadováno explicitní přetypování. Jako:'my_tbl'::text .

2. 'my_tbl'::text

Stejný řetězcový literál přetypuje na zadání text . Může obsahovat název tabulky, ale ve skutečnosti je to jen text.

3. 'my_tbl'::regclass

identifikátor objektu (OID) pro registrovanou třídu . Je zobrazen a lze jej zadat jako řetězec představující platný název objektu ('my_tbl' ). Výstup je automaticky kvalifikován pro schéma ('my_schema.my_tbl' ) a / nebo dvojité uvozovky ('"mY_TbL"' ), pokud by to bylo nejednoznačné nebo nezákonné jinak. Může to být běžný tabulka , sekvence , zobrazit , materializované zobrazení , složený typ atd. Podrobnosti v této související odpovědi:

4. my_tbl_var my_tbl (zkratka pro my_tbl_var my_tbl%ROWTYPE )

V DECLARE část bloku kódu plpgsql, což je deklarace proměnné s dobře známým typ řádku (také znám jako kompozitní typ). Typ musí být registrován v systémové tabulce pg_class (stejně jako u regclass proměnná). Není to OID odkazovaného objektu, ale jeho skutečný typ řádku. my_tbl_var a my_tbl oba jsou identifikátory zde a nelze jej parametrizovat. Můžete také odeslat libovolný řádek nebo záznam přímo:(123, 'foo')::my_tbl

5. my_tbl_var record

V DECLARE část bloku kódu plpgsql, která je deklarací anonymního záznam . V podstatě zástupný symbol pro dosud neznámý typ řádku / s dosud nedefinovanou strukturou. Lze jej použít ve většině z míst lze použít typ řádku. Ale nemůžete z něj přistupovat k polím, dokud není přiřazena proměnná záznamu.

Byl jste matoucí 1. , 3. a 4. a vyřešil to pomocí 5. místo toho.
Ale je toho dalších chyb zde:

  • Vybíráte celou tabulku, ale proměnná řádku (záznamu) může obsahovat pouze jeden řádek najednou. Takže pouze první je přiřazen a vrácen. I když neexistuje ORDER BY klauzule, výsledek je libovolný a může se kdykoli změnit. Zlá past.

  • Protože nyní používáte record typu, musíte se ujistit, že byl přiřazen, než budete moci spustit testy na jeho polích, jinak získáte výjimky pro prázdné tabulky. Ve vašem případě zaškrtněte record_var IS NULL dělá skoro stejnou práci. Ale pro řádky s NULL ve všech polích existuje rohový případ:pak record_var IS NULL hodnotí jako pravdivé. Ještě složitější pro test IS NOT NULL . Podrobnosti zde:

    Přidal jsem ukázku do SQL housle níže.

  • Funkce vrací jeden skalár (boolean ) hodnotu. Použijte:

    RETURN false;
    

    Místo:

    RETURN QUERY SELECT false;

Funkce

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;

SQL Fiddle (se dvěma variantami funkce a ukázkou pro řádek IS NULL).

Hlavní body

  • Použijte GET DIAGNOSTICS abyste zjistili, zda byly v dynamickém příkazu nalezeny nějaké řádky pomocí EXECUTE .

  • IF výraz lze zjednodušit.

  • Parametr je typu regclass , nejen název tabulky. Pro tento parametr bych nepoužil zavádějící název "tablename". To jen přispívá k vašemu počátečnímu zmatku. Nazývejte to _tbl místo toho.

Pokud byste se také chtěli vrátit sada proměnné typu řádku:



  1. MySQL SELECT a ORDER BY

  2. Store Procedure nevrací hodnotu v MVC5

  3. Použití Geekbench 3.2 k testování velkých databázových serverů

  4. PHP a MYSQL:použití bcrypt hash a ověření hesla s databází