Eu tenho uma função chamada update_total
que se parece com isso:
CREATE OR REPLACE FUNCTION update_total (table_name CHARACTER VARYING, year CHARACTER(4), donor_type CHARACTER VARYING, donor_code CHARACTER(5)) RETURNS VOID AS $$
DECLARE
table_name ALIAS FOR $1;
year ALIAS FOR $2;
donor_type ALIAS FOR $3;
donor_code ALIAS FOR $4;
query_statement TEXT;
BEGIN
query_statement :=
'
UPDATE gha.' || table_name || '
SET "' || year || '" = "' || year ||'_total"
FROM gha.' || table_name || ' "' || year || '",
(
SELECT
donor_type
, COALESCE(SUM("' || year || '"), 0) AS "' || year ||'_total"
FROM gha.' || table_name || '
WHERE donor_type = ''' || donor_type || '''
GROUP BY donor_type
) "new_data"
WHERE
gha.' || table_name || '.donor_code = ' || CAST(donor_code AS INT) || ';'
;
EXECUTE query_statement;
END;
$$ LANGUAGE plpgsql;
Ele atualiza uma linha em uma tabela que contém um valor agregado e eu chamo, por exemplo, assim:
SELECT update_total ('bilateral_oda_dac_1', '1990', 'Multilateral', '20002');
A tabela que ele atualiza é configurada para que existam colunas para cada ano em um intervalo, ou seja:
Column | Type
------------+-------------------
donor_code | smallint
donor_name | character varying
donor_type | character varying
1990 | numeric
1991 | numeric
1992 | numeric
...
Com esta função só posso atualizar o valor agregado em uma coluna por vez, mas gostaria de poder atualizar um intervalo de colunas de uma só vez, algo como:
CREATE FUNCTION update_all_total ()
RETURNS void LANGUAGE plpgsql AS
$BODY$
BEGIN
FOR i IN 1990 .. 1995
LOOP
PERFORM update_total ('bilateral_oda_dac_1', i, 'DAC', '20001');
END LOOP;
END;
$BODY$;
(Usei esta postagem para começar: https://stackoverflow.com/questions/11164409/sql-call-function-multiple-times-in-a-loop-postgres-8-3 ). O código cortado acima não funciona porque a função que estou usando usa uma string como entrada e estou passando um número inteiro. Como posso configurar o loop para passar strings para a função que estou chamando dentro dele?
Você pode usar
to_char()
,ou pode usar cast
::char(4)
.