Nastavení
Chcete vytvořit spouštěče (opakovaně?) pomocí stejné spouštěcí funkce, jak je uvedeno v mé související odpovědi na dba.SE . Chcete-li vytvořit více, musíte do spouštěcí funkce předat hodnoty řádky s více hodnoty sloupců, tedy dvourozměrné pole. (Ale můžeme pracovat s jakýmkoli jasně definovaný řetězec!)
Jediný způsob, jak předat hodnoty spouštěcí funkci PL/pgSQL (jiné než hodnoty sloupců spouštěcího řádku), jsou text
parametry, které jsou dostupné uvnitř funkce jako 0- založené pole textu ve speciální proměnné pole TG_ARGV[]
. Můžete předat proměnný počet parametrů, ale dříve jsme diskutovali o jediném řetězcovém literálu představujícím vaše 2-dimenzionální pole.
Vstup pochází z 2rozměrného pole Pythonu s celým číslem se znaménkem čísla, která zapadají do Postgres typu integer
. Použijte Postgres typ bigint
pro pokrytí celých čísel bez znaménka as okomentoval
.
Textová reprezentace v Pythonu vypadá takto:
[[1,2],[3,4]]
Syntaxe literálu pole Postgres:
{{1,2},{3,4}}
A chcete proces automatizovat.
Plná automatizace
Řetězec pro CREATE TRIGGER
můžete zřetězit příkazu ve vašem klientovi nebo můžete zachovat logiku ve funkci na straně serveru a pouze předat parametry.
Ukázka příkladu funkce s názvem tabulky a řetězcem, který je předán spouštěcí funkci. Spouštěcí funkce insaft_function()
je definováno ve vaší předchozí otázce na 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$;
Volejte:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
Nebo:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
db<>fiddle zde
Staré sqlfiddle
Nyní můžete předat buď [[1,2],[3,4]]
(s hranatými závorkami) nebo {{1,2},{3,4}}
(s kudrnatými závorkami). Oba fungují stejně. translate(_arg0, '[]', '{}'
transformuje první do druhého tvaru.
Tato funkce zruší spouštěč se stejným názvem, pokud existuje, před vytvořením nového. Možná budete chtít vypustit nebo ponechat tento řádek:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
Toto běží s oprávněními volající role DB. V případě potřeby byste jej mohli spustit s oprávněními superuživatele (nebo jinými). Viz:
Existuje mnoho způsobů, jak toho dosáhnout. Záleží na přesných požadavcích.
Vysvětlení format()
format()
a datový typ regclass
pomáhají bezpečně zřetězit příkaz DDL a znemožňují vkládání SQL. Viz:
Prvním argumentem je "formátovací řetězec" následovaný argumenty, které mají být vloženy do řetězce. Používám dolar-quoting
, což pro příklad není nezbytně nutné, ale obecně je to dobrý nápad pro zřetězení dlouhých řetězců obsahujících jednoduché uvozovky:$$DROP TRIGGER ... $$
format()
je modelován podle funkce C sprintf
. %1$s
je specifikátor formátu format()
funkce. Znamená to, že první (1$
) argument za formátovací řetězec je vložen jako řetězec bez uvozovek (%s
), odtud:%1$s
. První argument pro formátování je _tbl
v příkladu - regclass
parametr je automaticky vykreslen jako právní identifikátor, v případě potřeby uvozen, takže format()
nemusí dělat víc. Proto jen %s
, nikoli %I
(identifikátor). Podrobnosti naleznete v odkazované odpovědi výše.
Další používaný specifikátor formátu je %2$L
:Druhý argument jako citovaný řetězcový literál .
Pokud s format()
teprve začínáte , hrajte si s těmito jednoduchými příklady, abyste to pochopili:
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]', '[]', '{}'));