PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

INSERT с име на динамична таблица в тригерна функция

PostgreSQL 9.1 или по-нова версия

format() има вграден начин за избягване на идентификатори. По-просто от преди:

CREATE OR REPLACE FUNCTION foo_before()
  RETURNS trigger AS
$func$
BEGIN
   EXECUTE format('INSERT INTO %I.%I SELECT $1.*'
                , TG_TABLE_SCHEMA, TG_TABLE_NAME || 'shadow')
   USING OLD;

   RETURN OLD;
END
$func$  LANGUAGE plpgsql;

Работи с VALUES също и израз.

db<>цигулка тук
Стар sqlfiddle.

Основни точки

  • Използвайте format() или quote_ident() да цитира идентификатори (автоматично и само когато е необходимо), като по този начин се защитава срещу SQL инжектиране и прости нарушения на синтаксиса.
    Това е необходимо , дори със собствените си имена на таблици!
  • Квалифицирайте по схема името на таблицата. В зависимост от текущия search_path задаването на просто име на таблица може в противен случай да се разреши до друга таблица със същото име в различна схема.
  • Използвайте EXECUTE за динамични DDL изрази.
  • Предаване на стойности безопасно с USING клауза.
  • Вижте изящното ръководство за изпълнение на динамични команди в plpgsql.
  • Обърнете внимание, чеRETURN OLD; във функцията за задействане се изисква за задействане BEFORE DELETE . Подробности в ръководството тук.

Получавате съобщение за грешка във вашата почти успешна версия, защото OLD ене се вижда вътре EXECUTE . И ако искате да конкатенирате отделни стойности на декомпозирания ред, както опитахте, трябва да подготвите текстовото представяне на всяка отделна колона с quote_literal() за да се гарантира валиден синтаксис. Вие също трябва да знаете имена на колони предварително, за да се справите с тях или да направите заявка в системните каталози - което противоречи на идеята ви да имате проста, динамична функция за задействане...

Моето решение избягва всички тези усложнения. Също така малко опростен.

PostgreSQL 9.0 или по-стара версия

format() все още не е наличен, така че:

CREATE OR REPLACE FUNCTION foo_before()
  RETURNS trigger AS
$func$
BEGIN
    EXECUTE 'INSERT INTO ' || quote_ident(TG_TABLE_SCHEMA)
                    || '.' || quote_ident(TG_TABLE_NAME || 'shadow')
                    || ' SELECT $1.*'
    USING OLD;

    RETURN OLD;
END
$func$  LANGUAGE plpgsql;

Свързано:

  • Как да използвам динамично TG_TABLE_NAME в PostgreSQL 8.2?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Инсталирайте utf8 collation в PostgreSQL

  2. Cloud9 постгрес

  3. Как Transaction_timestamp() работи в PostgreSQL

  4. Вижте и изчистите Postgres кешове/буфери?

  5. Как да конвертирате jsonb типа на PostgreSQL 9.4 в float