sql >> Databasteknik >  >> RDS >> PostgreSQL

Få tillgång till dynamiskt kolumnnamn för radtyp i triggerfunktionen

Detta borde göra det:

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;

Den omedelbara orsaken till felmeddelandet var den yttre SELECT . Utan mål måste du ersätta det med PERFORM i plpgsql. Men den inre PERFORM i frågesträngen som skickades till EXECUTE var fel också. PERFORM är ett plpgsql-kommando, inte giltigt i en SQL-sträng som skickas till EXECUTE , som förväntar sig SQL-kod. Du måste använda SELECT där. Äntligen OLD och NEW är inte synliga i EXECUTE och skulle var och en ta upp ett eget undantag som du hade det. Alla problem åtgärdas genom att släppa EXECUTE .

Ett enkelt och snabbt sätt att få värdet av ett dynamiskt kolumnnamn från radtyperna OLD och NEW :casta till json , då kan du parametrisera nyckelnamnet som visas. Borde vara lite enklare och snabbare än alternativet med dynamisk SQL - vilket också är möjligt, som:

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

Relaterat:

Bortsett från:Inte säker på varför du behöver de tunga låsen.

Bortsett från 2:Överväg att skriva en separat triggerfunktion för varje trigger istället. Mer bullrig DDL, men enklare och snabbare att köra.



  1. App för att övervaka PostgreSQL-frågor i realtid?

  2. Får odefinierat index medan kolumnvärde hämtas från mysql

  3. Varför använder MySQL latin1_swedish_ci som standard?

  4. mysql hur konverterar man varchar(10) till TIMESTAMP?