Det er vigtigt at forstå hovedkarakteren af disse fem forskellige slags data/symboler :
1. 'my_tbl'
En streng bogstavelig af unknown
type . Når den bruges i SQL (indlejret i plpgsql-kode eller ej), tvinges den til en type, der er afledt af konteksten . Hvis typen ikke kan bestemmes, kan det være nødvendigt med en eksplicit afstøbning. Ligesom:'my_tbl'::text
.
2. 'my_tbl'::text
Den samme streng cast til skriv text
. Det kan indeholde navnet på en tabel, men det er egentlig bare tekst.
3. 'my_tbl'::regclass
En objekt-id (OID)
for en registreret klasse . Det vises og kan indtastes som en streng, der repræsenterer et gyldigt objektnavn ('my_tbl'
). Outputtet er automatisk skema-kvalificeret ('my_schema.my_tbl'
) og/eller dobbelt anførselstegn ('"mY_TbL"'
), hvis det ellers ville være tvetydigt eller ulovligt. Det kan være et almindeligt bord , sekvens , se , materialiseret visning , sammensat type osv. Detaljer i dette relaterede svar:
4. my_tbl_var my_tbl
(en forkortelse for my_tbl_var my_tbl%ROWTYPE
)
I DECLARE
sektion af en plpgsql-kodeblok, der er en variabel erklæring med en velkendt rækketype
(a.k.a. sammensat type). Typen skal registreres i systemtabellen pg_class
(samme som med en regclass
variabel). Det er ikke OID'et for det refererede objekt, men dets faktiske rækketype. my_tbl_var
og my_tbl
er begge identifikatorer her og kan ikke parametreres. Du kan også caste en hvilken som helst række eller optage direkte:(123, 'foo')::my_tbl
5. my_tbl_var record
I DECLARE
sektion af en plpgsql-kodeblok, der er erklæringen af en anonym optagelse
. Dybest set en pladsholder for en endnu ukendt rækketype / med endnu udefineret struktur. Den kan bruges i de fleste af stederne kan en rækketype bruges. Men du kan ikke få adgang til felter fra den, før registreringsvariablen er tildelt.
Du forvirrede 1. , 3. og 4. og løste det ved at bruge 5. i stedet.
Men der er mere, der går galt her:
-
Du vælger en hel tabel, men en række (record) variabel kan kun indeholde en række ad gangen. Så kun den første tildeles og returneres. Mens der ikke er nogen
ORDER BY
klausul, er resultatet vilkårligt og kan ændres til enhver tid. Ondskabsfælde. -
Da du nu bruger en
record
type, skal du sikre dig, at den er blevet tildelt, før du kan køre test på dens felter, ellers vil du få undtagelser for tomme tabeller. I dit tilfælde er markeringenrecord_var IS NULL
gør næsten det samme arbejde. Men der er en hjørne-case for rækker med NULL i alle felter:derefterrecord_var IS NULL
vurderes til sandt. Endnu vanskeligere for testenIS NOT NULL
. Detaljer her:Jeg har føjet en demo til SQL violinen nedenfor.
-
Funktionen returnerer en enkelt skalar (
boolean
) værdi. Brug:RETURN false;
I stedet for:
RETURN QUERY SELECT false;
Funktion
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 (med to varianter af funktionen og en demo for række ER NULL).
Vigtige punkter
-
Brug
GET DIAGNOSTICS
for at finde ud af, om der blev fundet nogle rækker i en dynamisk sætning medEXECUTE
. -
IF
udtryk kan forenkles. -
Parameteren er af typen
regclass
, ikke kun et bordnavn. Jeg ville ikke bruge det vildledende navn "tabelnavn" til denne parameter. Det øger kun din indledende forvirring. Kalder det_tbl
i stedet.
Hvis du også vil vende tilbage et sæt variabel rækketype: