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?