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
recordgebruikt, 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 NULLdoet bijna hetzelfde werk. Maar er is een hoekgeval voor rijen met NULL in alle velden:danrecord_var IS NULLwaardeert 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 DIAGNOSTICSom erachter te komen of er rijen zijn gevonden in een dynamische instructie metEXECUTE. -
De
IFuitdrukking 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_tblin plaats daarvan.
Als je ook wilt retourneren een reeks variabele rijtypes: