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_path
het instellen van een kale tabelnaam kan anders worden omgezet in een andere tabel met dezelfde naam in een ander schema. - Gebruik
EXECUTE
voor dynamische DDL-instructies. - Geef waarden door veilig met de
USING
clausule. - 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?