PostgreSQL 9.1 of hoger
format() heeft een ingebouwde manier om aan identifiers te ontsnappen. Eenvoudiger dan voorheen:
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;
Werkt met een VALUES uitdrukking ook.
db<>viool hier
Oude sqlfiddle.
Belangrijkste punten
- Gebruik
format()ofquote_ident()om identifiers te citeren (automatisch en alleen waar nodig), en zo te beschermen tegen SQL-injectie en eenvoudige syntaxisschendingen.
Dit is noodzakelijk , zelfs met je eigen tafelnamen! - Schema-kwalificeer de tabelnaam. Afhankelijk van het huidige
search_pathhet instellen van een kale tabelnaam kan anders worden omgezet in een andere tabel met dezelfde naam in een ander schema. - Gebruik
EXECUTEvoor dynamische DDL-instructies. - Geef waarden door veilig met de
USINGclausule. - Raadpleeg de goede handleiding over het uitvoeren van dynamische opdrachten in plpgsql.
- Let op
RETURN OLD;in de triggerfunctie is vereist voor een triggerBEFORE DELETE. Details in de handleiding hier.
U krijgt de foutmelding in uw bijna succesvolle versie omdat OLD is niet zichtbaar binnen EXECUTE . En als je individuele waarden van de ontlede rij wilt samenvoegen zoals je hebt geprobeerd, moet je de tekstrepresentatie van elke afzonderlijke kolom voorbereiden met quote_literal() om een geldige syntaxis te garanderen. Je zou ook moeten weten kolomnamen vooraf om ze af te handelen of de systeemcatalogi te doorzoeken - wat indruist tegen uw idee van een eenvoudige, dynamische triggerfunctie ...
Mijn oplossing vermijdt al deze complicaties. Ook een beetje vereenvoudigd.
PostgreSQL 9.0 of eerder
format() is nog niet beschikbaar, dus:
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;
Gerelateerd:
- Hoe dynamisch gebruik te maken van TG_TABLE_NAME in PostgreSQL 8.2?