Configuração
Você deseja criar gatilhos (repetidamente?) usando a mesma função de gatilho, conforme descrito em minha resposta relacionada em dba.SE . Você precisa passar valores para a função de gatilho para criar múltiplos linhas com múltiplas valores de coluna, daí a matriz bidimensional. (Mas podemos trabalhar com qualquer string claramente definida!)
A única maneira de passar valores para uma função de gatilho PL/pgSQL (além dos valores de coluna da linha de gatilho) é
text
parâmetros, que são acessíveis dentro da função como 0- matriz de texto baseada na variável de matriz especial TG_ARGV[]
. Você pode passar um número variável de parâmetros, mas discutimos uma única string literal representando seu array bidimensional anteriormente. A entrada vem de uma matriz Python bidimensional com inteiro assinado números, que se encaixam no tipo Postgres
integer
. Use o tipo Postgres bigint
para cobrir números inteiros não assinados, como comentou
. A representação de texto em Python é assim:
[[1,2],[3,4]]
Sintaxe para um literal de matriz Postgres:
{{1,2},{3,4}}
E você quer automatizar o processo.
Automação total
Você pode concatenar a string para o
CREATE TRIGGER
instrução em seu cliente ou você pode persistir a lógica em uma função do lado do servidor e apenas passar parâmetros. Demonstrando uma função de exemplo que recebe um nome de tabela e a string que é passada para a função de gatilho. A função de gatilho
insaft_function()
está definido em sua pergunta anterior sobre 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$;
Ligar:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
Ou:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
db<>fiddle aqui
Antigo sqlfiddle
Agora você pode passar
[[1,2],[3,4]]
(com colchetes) ou {{1,2},{3,4}}
(com chaves). Ambos funcionam da mesma forma. translate(_arg0, '[]', '{}'
transforma a primeira na segunda forma. Esta função descarta um gatilho de mesmo nome, se existir, antes de criar o novo. Você pode querer descartar ou manter esta linha:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
Isso é executado com os privilégios da função de banco de dados de chamada. Você pode fazê-lo rodar com privilégios de superusuário (ou qualquer outro) se necessário. Ver:
Há muitas maneiras de conseguir isso. Depende dos requisitos exatos.
Explicando format()
format()
e o tipo de dados regclass
ajudam a concatenar com segurança o comando DDL e impossibilitam a injeção de SQL. Ver:O primeiro argumento é a "string de formato", seguido pelos argumentos a serem incorporados na string. Eu uso cotações de dólares , que não é estritamente necessário para o exemplo, mas geralmente é uma boa ideia para concatenar longas strings contendo aspas simples:
$$DROP TRIGGER ... $$
formato()
é modelado ao longo da função C sprintf
. %1$s
é um especificador de formato do formato ( )
função. Isso significa que o primeiro (1$
) após a string de formato ser inserida como string sem aspas (%s
), portanto:%1$s
. O primeiro argumento para formatar é _tbl
no exemplo - a regclass
parâmetro é renderizado como identificador legal automaticamente, com aspas duplas se necessário, então format()
não precisa fazer mais. Portanto, apenas %s
, não %I
(identificador). Leia a resposta vinculada acima para obter detalhes.O outro especificador de formato em uso é
%2$L
:Segundo argumento como literal de string entre aspas . Se você é novo em
format()
, brinque com estes exemplos simples para entender: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]', '[]', '{}'));
E leia o manual .