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 BYklausul, er resultatet vilkårligt og kan ændres til enhver tid. Ondskabsfælde. -
Da du nu bruger en
recordtype, 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 NULLgør næsten det samme arbejde. Men der er en hjørne-case for rækker med NULL i alle felter:derefterrecord_var IS NULLvurderes 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 DIAGNOSTICSfor at finde ud af, om der blev fundet nogle rækker i en dynamisk sætning medEXECUTE. -
IFudtryk 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_tbli stedet.
Hvis du også vil vende tilbage et sæt variabel rækketype: