PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Uzyskaj dostęp do dynamicznej nazwy kolumny typu wiersza w funkcji wyzwalacza

To powinno wystarczyć:

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;

Bezpośrednią przyczyną komunikatu o błędzie był zewnętrzny SELECT . Bez celu musisz go zastąpić PERFORM w plpgsql. Ale wewnętrzny PERFORM w ciągu zapytania przekazanym do EXECUTE też się mylił. PERFORM jest poleceniem plpgsql, niepoprawnym w ciągu SQL przekazanym do EXECUTE , który oczekuje kodu SQL. Musisz użyć SELECT tam. Wreszcie OLD i NEW nie są widoczne w EXECUTE i każdy z nich zgłosi swój własny wyjątek tak, jak ty go miałeś. Wszystkie problemy są naprawiane przez upuszczenie PERFORM .

Prosty i szybki sposób na uzyskanie wartości dynamicznej nazwy kolumny z typów wierszy OLD i NEW :rzutuj na json , możesz sparametryzować nazwę klucza, jak pokazano. Powinna być nieco prostsza i szybsza niż alternatywa z dynamicznym SQL - co również jest możliwe, na przykład:

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

Powiązane:

Na bok:Nie wiem, dlaczego potrzebujesz ciężkich zamków.

Na bok 2:Rozważ napisanie osobnej funkcji wyzwalacza dla każdego wyzwalacza. Bardziej hałaśliwe DDL, ale prostsze i szybsze do wykonania.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Algebraiczne typy danych w Postgres

  2. jak używać typu Blob w Postgresie

  3. BŁĄD:zapytanie nie ma miejsca docelowego dla danych wynikowych

  4. Klucze podstawowe i obce w pgAdmin

  5. Funkcja Postgresql nie zwraca tabeli po wybraniu