PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Generischer Auslöser zum Einschränken von Einfügungen basierend auf der Anzahl

Ich habe eine ähnliche Art von generischen Triggern gemacht. Der schwierigste Teil ist, den Werteintrag in NEW zu bekommen Datensatz basierend auf dem Spaltennamen.

Ich mache es folgendermaßen:

  • konvertiere NEW Daten in Array;
  • finden Sie den attnum der Spalte und verwenden Sie sie als Index für das Array.

Dieser Ansatz funktioniert solange die Daten keine Kommas enthalten :( Ich kenne keine andere Möglichkeit, NEW umzuwandeln oder OLD Variablen in das Array von Werten.

Die folgende Funktion könnte helfen:

CREATE OR REPLACE FUNCTION impose_maximum() RETURNS trigger AS $impose_maximum$
DECLARE
  _sql  text;
  _cnt  int8;
  _vals text[];
  _anum int4;
  _im   record;

BEGIN
 _vals := string_to_array(translate(trim(NEW::text), '()', ''), ',');

 FOR _im IN SELECT * FROM imposed_maximums WHERE table_name = TG_TABLE_NAME LOOP
  SELECT attnum INTO _anum FROM pg_catalog.pg_attribute a
    JOIN pg_catalog.pg_class t ON t.oid = a.attrelid
   WHERE t.relkind = 'r' AND t.relname = TG_TABLE_NAME
     AND NOT a.attisdropped AND a.attname = _im.column_group;

  _sql := 'SELECT count('||quote_ident(_im.column_count)||')'||
          ' FROM '||quote_ident(_im.table_name)||
          ' WHERE '||quote_ident(_im.column_group)||' = $1';

  EXECUTE _sql INTO _cnt USING _vals[_anum];

  IF _cnt > CAST(_im.max_size AS int8) THEN
    RAISE EXCEPTION 'Maximum of % hit for column % in table %(%=%)',
      _im.max_size, _im.column_count,
      _im.table_name, _im.column_group, _vals[_anum];
  END IF;
 END LOOP;

 RETURN NEW;
END; $impose_maximum$ LANGUAGE plpgsql;

Diese Funktion überprüft alle Bedingungen, die für eine bestimmte Tabelle definiert sind.