Opsætning
Du vil oprette triggere (gentagne gange?) ved hjælp af den samme triggerfunktion som beskrevet i mit relaterede svar på dba.SE . Du skal sende værdier til triggerfunktionen for at oprette flere rækker med flere kolonneværdier, deraf det todimensionelle array. (Men vi kan arbejde med hvilken som helst klart defineret streng!)
Den eneste måde at overføre værdier til en PL/pgSQL-triggerfunktion (ud over kolonneværdier i den udløsende række) er tekst
parametre, som er tilgængelige i funktionen som 0- baseret array af tekst i den specielle array-variabel TG_ARGV[]
. Du kan sende et variabelt antal parametre, men vi diskuterede en enkelt streng, der repræsenterer dit 2-dimensionelle array tidligere.
Input kommer fra et 2-dimensionelt Python-array med heltal med fortegn tal, der passer ind i Postgres-typen heltal
. Brug Postgres-typen bigint
for at dække usignerede heltal, as kommenterede
.
Tekstgengivelsen i Python ser sådan ud:
[[1,2],[3,4]]
Syntaks for en Postgres array literal:
{{1,2},{3,4}}
Og du vil automatisere processen.
Fuld automatisering
Du kan sammenkæde strengen for CREATE TRIGGER
sætning i din klient, eller du kan fortsætte logikken i en server-side funktion og bare sende parametre.
Demonstrering af en eksempelfunktion, der tager et tabelnavn og den streng, der er sendt til triggerfunktionen. Udløserfunktionen insaft_function()
er defineret i dit tidligere spørgsmål på 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$;
Ring til:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
Eller:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
db<>fiddle her
Gamle sqlfiddle
Nu kan du sende enten [[1,2],[3,4]]
(med firkantede parenteser) eller {{1,2},{3,4}}
(med krøllede seler). Begge fungerer det samme. translate(_arg0, '[]', '{}'
omdanner den første til den anden form.
Denne funktion dropper en trigger af samme navn, hvis den findes, før den nye oprettes. Du vil måske droppe eller beholde denne linje:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
Dette kører med privilegierne for den kaldende DB-rolle. Du kan få det til at køre med superbruger (eller andre) privilegier, hvis det er nødvendigt. Se:
Der er mange måder at opnå dette på. Det afhænger af præcise krav.
Forklaring af format()
format()
og datatypen regclass
hjælpe til sikkert at sammenkæde DDL-kommandoen og gøre SQL-injektion umulig. Se:
Det første argument er "formatstrengen", efterfulgt af argumenter, der skal indlejres i strengen. Jeg bruger notering i dollars
, hvilket ikke er strengt nødvendigt for eksemplet, men generelt en god idé til at sammenkæde lange strenge, der indeholder enkelte anførselstegn:$$DROP TRIGGER ... $$
format()
er modelleret efter C-funktionen sprintf
. %1$s
er en formatspecifikation af format( )
fungere. Det betyder, at den første (1$
) argument efter formatstrengen er indsat som uanført streng (%s
), derfor:%1$s
. Det første argument til formatering er _tbl
i eksemplet - regclass
parameter gengives automatisk som juridisk identifikator, dobbelt anførselstegn om nødvendigt, så format()
behøver ikke gøre mere. Derfor kun %s
, ikke %I
(identifikator). Læs det linkede svar ovenfor for detaljer.
Den anden formatangivelse, der bruges, er %2$L
:Andet argument som citeret streng bogstavelig .
Hvis du er ny til format()
, leg med disse enkle eksempler for at forstå:
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]', '[]', '{}'));
Og læs manualen .