sql >> Database >  >> RDS >> PostgreSQL

Toegang tot dynamische kolomnaam van rijtype in triggerfunctie

Dit zou het moeten doen:

CREATE OR REPLACE FUNCTION device_bid_modifiers_count_per()
  RETURNS TRIGGER AS
$func$
DECLARE
   devices_count int      := device_types_count();
   table_name    regclass := TG_ARGV[0];
   column_name   text     := TG_ARGV[1];
BEGIN
   LOCK TABLE device_types IN EXCLUSIVE MODE;
   EXECUTE format('LOCK TABLE %s IN EXCLUSIVE MODE', table_name);

   IF TG_OP = 'DELETE' THEN
      PERFORM validate_bid_modifiers_count(table_name
                                         , column_name
                                         , (row_to_json(OLD) ->> column_name)::bigint
                                         , devices_count);
   ELSE
      PERFORM validate_bid_modifiers_count(table_name
                                         , column_name
                                         , (row_to_json(NEW) ->> column_name)::bigint
                                         , devices_count);
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

De directe oorzaak van de foutmelding was de buitenste SELECT . Zonder doel moet je het vervangen door PERFORM in plpgsql. Maar de innerlijke PERFORM in de queryreeks doorgegeven aan EXECUTE was ook fout. PERFORM is een plpgsql-opdracht, niet geldig in een SQL-string die wordt doorgegeven aan EXECUTE , die SQL-code verwacht. Je moet SELECT . gebruiken daar. Eindelijk OLD en NEW zijn niet zichtbaar in EXECUTE en zou elk een eigen uitzondering opwerpen zoals jij het had. Alle problemen worden opgelost door EXECUTE . te verwijderen .

Een eenvoudige en snelle manier om de waarde van een dynamische kolomnaam te verkrijgen uit de rijtypen OLD en NEW :casten naar json , dan kunt u de sleutelnaam parametriseren zoals aangetoond. Zou iets eenvoudiger en sneller moeten zijn dan het alternatief met dynamische SQL - wat ook mogelijk is, zoals:

  ...
  EXECUTE format('SELECT validate_bid_modifiers_count(table_name
                                                    , column_name
                                                    , ($1.%I)::bigint
                                                    , devices_count)', column_name)
  USING OLD;
  ...

Gerelateerd:

Terzijde:ik weet niet zeker waarom je de zware sloten nodig hebt.

Terzijde 2:Overweeg in plaats daarvan een aparte triggerfunctie te schrijven voor elke trigger. Meer luidruchtige DDL, maar eenvoudiger en sneller uit te voeren.



  1. Kan de null-waarde van JSON_EXTRACT niet detecteren

  2. Hoe controleer je of een array een bepaalde string bevat?

  3. Maak een xml root element voor een clob die geen root element heeft in Oracle

  4. Postgres-functie die tabel retourneert en geen gegevens in kolommen retourneert