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ěterecord_var IS NULL
dělá skoro stejnou práci. Ale pro řádky s NULL ve všech polích existuje rohový případ:pakrecord_var IS NULL
hodnotí jako pravdivé. Ještě složitější pro testIS 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: