Instellen
U wilt (herhaaldelijk?) triggers maken met dezelfde triggerfunctie zoals beschreven in mijn gerelateerde antwoord op dba.SE . U moet waarden doorgeven aan de triggerfunctie om meerdere te maken rijen met meerdere kolomwaarden, vandaar de tweedimensionale matrix. (Maar we kunnen werken met elke duidelijk gedefinieerde string!)
De enige manier om waarden door te geven aan een PL/pgSQL-triggerfunctie (anders dan kolomwaarden van de activerende rij) is text
parameters, die binnen de functie toegankelijk zijn als 0- gebaseerde array van tekst in de speciale arrayvariabele TG_ARGV[]
. U kunt een variabel aantal parameters doorgeven, maar we hebben eerder een enkele letterlijke tekenreeks besproken die uw 2-dimensionale array vertegenwoordigt.
Invoer komt van een 2-dimensionale Python-array met ondertekend geheel getal getallen, die passen in het Postgres-type integer
. Gebruik het Postgres-type bigint
om ongetekende gehele getallen te dekken, als heeft gereageerd
.
De tekstrepresentatie in Python ziet er als volgt uit:
[[1,2],[3,4]]
Syntaxis voor een letterlijke Postgres-array:
{{1,2},{3,4}}
En u wilt het proces automatiseren.
Volledige automatisering
U kunt de tekenreeks samenvoegen voor de CREATE TRIGGER
statement in uw client of u kunt de logica in een server-side functie behouden en gewoon parameters doorgeven.
Demonstratie van een voorbeeldfunctie met een tabelnaam en de tekenreeks die wordt doorgegeven aan de triggerfunctie. De triggerfunctie insaft_function()
is gedefinieerd in uw vorige vraag op dba.SE
.
CREATE OR REPLACE FUNCTION f_create_my_trigger(_tbl regclass, _arg0 text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format($$
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
CREATE TRIGGER insaft_%1$s_ids
AFTER INSERT ON %1$s
FOR EACH ROW EXECUTE PROCEDURE insaft_function(%2$L)$$
, _tbl
, translate(_arg0, '[]', '{}')
);
END
$func$;
Bel:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
Of:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
db<>fiddle hier
Oude sqlfiddle
Nu kun je ofwel [[1,2],[3,4]]
(met vierkante haken) of {{1,2},{3,4}}
(met accolades). Beide werken hetzelfde. translate(_arg0, '[]', '{}'
transformeert de eerste in de tweede vorm.
Deze functie laat een trigger met dezelfde naam vallen als deze bestaat, voordat de nieuwe wordt gemaakt. Misschien wilt u deze regel laten vallen of behouden:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
Dit wordt uitgevoerd met de privileges van de aanroepende DB-rol. Je zou het indien nodig kunnen laten draaien met superuser (of andere) privileges. Zie:
Er zijn veel manieren om dit te bereiken. Het hangt af van de exacte vereisten.
Uitleg format()
format()
en het gegevenstype regclass
helpen om het DDL-commando veilig samen te voegen en SQL-injectie onmogelijk te maken. Zie:
Het eerste argument is de "format string", gevolgd door argumenten die in de string moeten worden ingesloten. Ik gebruik dollar-quoting
, wat niet strikt noodzakelijk is voor het voorbeeld, maar over het algemeen een goed idee voor het aaneenschakelen van lange tekenreeksen met enkele aanhalingstekens:$$DROP TRIGGER ... $$
format()
is gemodelleerd langs de C-functie sprintf
. %1$s
is een formaatspecificatie van het format()
functie. Het betekent dat de eerste (1$
) argument nadat de opmaaktekenreeks is ingevoegd als niet-aangehaalde tekenreeks (%s
), vandaar:%1$s
. Het eerste argument om te formatteren is _tbl
in het voorbeeld - de regclass
parameter wordt automatisch weergegeven als legale identifier, indien nodig dubbele aanhalingstekens, dus format()
hoeft niet meer te doen. Vandaar gewoon %s
, niet %I
(identificatienummer). Lees het gekoppelde antwoord hierboven voor details.
De andere gebruikte formaatspecificatie is %2$L
:Tweede argument als letterlijke tekenreeks tussen aanhalingstekens .
Als u nieuw bent bij format()
, speel met deze eenvoudige voorbeelden om het te begrijpen:
SELECT format('input -->|%s|<-- here', '[1,2]')
, format('input -->|%s|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%L|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%I|<-- here', translate('[1,2]', '[]', '{}'));
En lees de handleiding .