Inställningar
Du vill skapa triggers (upprepade gånger?) med samma triggerfunktion som beskrivs i mitt relaterade svar på dba.SE . Du måste skicka värden till triggerfunktionen för att skapa multipel rader med flera kolumnvärden, därav den tvådimensionella matrisen. (Men vi kan arbeta med alla tydligt definierad sträng!)
Det enda sättet att skicka värden till en PL/pgSQL-utlösarfunktion (förutom kolumnvärdena för den utlösande raden) är text
parametrar, som är tillgängliga i funktionen som 0- baserad array av text i den speciella arrayvariabeln TG_ARGV[]
. Du kan skicka ett variabelt antal parametrar, men vi diskuterade en enda sträng som representerar din 2-dimensionella array tidigare.
Indata kommer från en 2-dimensionell Python-array med teckental siffror, som passar in i Postgres-typen heltal
. Använd Postgres-typen bigint
för att täcka osignerade heltal, as kommenterade
.
Textrepresentationen i Python ser ut så här:
[[1,2],[3,4]]
Syntax för en Postgres array literal:
{{1,2},{3,4}}
Och du vill automatisera processen.
Full automatisering
Du kan sammanfoga strängen för CREATE TRIGGER
uttalande i din klient eller så kan du bevara logiken i en funktion på serversidan och bara skicka parametrar.
Demonstrera en exempelfunktion med ett tabellnamn och strängen som skickas till triggerfunktionen. Triggerfunktionen insaft_function()
definieras i din tidigare fråga 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:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
Eller:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
Nu kan du skicka antingen [[1,2],[3,4]]
(med hakparenteser) eller {{1,2},{3,4}}
(med lockiga hängslen). Båda fungerar likadant. translate(_arg0, '[]', '{}'
omvandlar den första till den andra formen.
Den här funktionen släpper en trigger med samma namn om den finns, innan den nya skapas. Du kanske vill släppa eller behålla den här raden:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
Detta körs med privilegierna för den anropande DB-rollen. Du kan få den att köras med superanvändarbehörigheter (eller andra) om det behövs. Se:
Det finns många sätt att uppnå detta. Det beror på exakta krav.
Förklara format()
format()
och datatypen regclass
hjälpa till att säkert sammanfoga DDL-kommandot och göra SQL-injektion omöjlig. Se:
Det första argumentet är "formatsträngen", följt av argument som ska bäddas in i strängen. Jag använder dollarnotering
, vilket inte är strikt nödvändigt för exemplet, men generellt sett en bra idé för att sammanfoga långa strängar som innehåller enkla citattecken:$$DROP TRIGGER ... $$
format()
är modellerad efter C-funktionen sprintf
. %1$s
är en formatspecifikation av format( )
fungera. Det betyder att den första (1$
) argument efter att formatsträngen har infogats som sträng utan citationstecken (%s
), därav:%1$s
. Det första argumentet att formatera är _tbl
i exemplet - regclass
parametern renderas automatiskt som legal identifierare, dubbla citattecken vid behov, så format()
behöver inte göra mer. Därför bara %s
, inte %I
(identifierare). Läs det länkade svaret ovan för detaljer.
Den andra formatspecifikationen som används är %2$L
:Andra argumentet som citerad sträng bokstavlig .
Om du är ny på format()
, lek med dessa enkla exempel för att förstå:
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]', '[]', '{}'));
Och läs manualen .