Het is belangrijk om de belangrijkste aard van deze vijf verschillende soorten gegevens / symbolen te begrijpen :
1. 'my_tbl'
Een letterlijke tekenreeks van unknown
typ . Bij gebruik in SQL (ingesloten in plpgsql-code of niet), wordt het gedwongen tot een type dat is afgeleid van de context . Als het type niet kan worden bepaald, kan een expliciete cast vereist zijn. Zoals:'my_tbl'::text
.
2. 'my_tbl'::text
Dezelfde letterlijke tekenreeks naar typ text
. Het kan de naam van een tabel bevatten, maar het is eigenlijk alleen maar tekst.
3. 'my_tbl'::regclass
Een object-ID (OID)
voor een geregistreerde les . Het wordt weergegeven en kan worden ingevoerd als tekenreeks die een geldige objectnaam vertegenwoordigt ('my_tbl'
). De uitvoer is automatisch schema-gekwalificeerd ('my_schema.my_tbl'
) en/of dubbele aanhalingstekens ('"mY_TbL"'
) als het anders dubbelzinnig of illegaal zou zijn. Het kan een gewone tafel zijn , reeks , bekijken , gerealiseerde weergave , composiettype etc. Details in dit gerelateerde antwoord:
4. my_tbl_var my_tbl
(afkorting van my_tbl_var my_tbl%ROWTYPE
)
In de DECLARE
sectie van een plpgsql-codeblok dat een variabele declaratie is met een bekende rijtype
(ook bekend als composiettype). Het type moet worden geregistreerd in de systeemtabel pg_class
(hetzelfde als bij een regclass
variabel). Het is niet de OID van het object waarnaar wordt verwezen, maar het werkelijke rijtype. my_tbl_var
en my_tbl
zijn beide identificaties hier en kan niet worden geparametriseerd. Je kunt ook elke rij of record direct casten:(123, 'foo')::my_tbl
5. my_tbl_var record
In de DECLARE
sectie van een plpgsql-codeblok dat de verklaring is van een anonieme record
. Kortom, een tijdelijke aanduiding voor een nog onbekend rijtype / met een nog ongedefinieerde structuur. Het kan worden gebruikt in de meeste van de plaatsen kan een rijtype worden gebruikt. Maar u kunt er geen velden uit openen voordat de recordvariabele is toegewezen.
Je verwarde 1. , 3. en 4. en loste het op door 5 te gebruiken. in plaats daarvan.
Maar er gaat meer mis hier:
-
U selecteert een hele tabel, maar een rij (record)variabele kan slechts één rij tegelijk bevatten. Dus alleen de eerste wordt toegewezen en geretourneerd. Hoewel er geen
ORDER BY
. is clausule, is het resultaat willekeurig en kan het op elk moment veranderen. Kwaadaardige valstrik. -
Aangezien u nu een
record
gebruikt, type, moet u ervoor zorgen dat het is toegewezen voordat u tests op zijn velden kunt uitvoeren, anders krijgt u uitzonderingen voor lege tabellen. In uw geval het selectievakjerecord_var IS NULL
doet bijna hetzelfde werk. Maar er is een hoekgeval voor rijen met NULL in alle velden:danrecord_var IS NULL
waardeert tot waar. Nog lastiger voor de testIS NOT NULL
. Details hier:Ik heb een demo toegevoegd aan de SQL-viool hieronder.
-
De functie retourneert een enkele scalaire waarde (
boolean
) waarde. Gebruik:RETURN false;
In plaats van:
RETURN QUERY SELECT false;
Functie
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 (met twee varianten van de functie en een demo voor rij IS NULL).
Belangrijkste punten
-
Gebruik
GET DIAGNOSTICS
om erachter te komen of er rijen zijn gevonden in een dynamische instructie metEXECUTE
. -
De
IF
uitdrukking kan worden vereenvoudigd. -
De parameter is van het type
regclass
, niet alleen een tafelnaam. Ik zou de misleidende naam "tabelnaam" niet gebruiken voor deze parameter. Dat draagt alleen maar bij aan uw aanvankelijke verwarring. Noem het_tbl
in plaats daarvan.
Als je ook wilt retourneren een reeks variabele rijtypes: