sql >> Database >  >> RDS >> PostgreSQL

plpgsql - dynamische tabelnaam gebruiken in declare-statement

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 selectievakje record_var IS NULL doet bijna hetzelfde werk. Maar er is een hoekgeval voor rijen met NULL in alle velden:dan record_var IS NULL waardeert tot waar. Nog lastiger voor de test IS 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 met EXECUTE .

  • 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:



  1. Portletposities opslaan

  2. Authenticatie-plug-in 'caching_sha2_password' kan niet worden geladen

  3. upload meerdere bestanden naar de server en schrijf naar de database

  4. Hoe PHP-testserver instellen in Dreamweaver?