Ваше решение является жизнеспособным способом. Я в значительной степени переписал вашу функцию plpgsql для упрощения / производительности / читаемости / безопасности.
CREATE OR REPLACE FUNCTION f_taxamount()
RETURNS void AS
$BODY$
DECLARE
rec record;
BEGIN
DROP TABLE IF EXISTS tmptable;
EXECUTE 'CREATE TABLE tmptable (invoiceid integer PRIMARY KEY, '
|| (
SELECT string_agg(col || ' numeric(9,2) DEFAULT 0', ', ')
FROM (
SELECT quote_ident(lower(replace(taxname,' ','_'))) AS col
FROM tbltaxamount
GROUP BY 1
ORDER BY 1
) x
)
|| ')';
EXECUTE '
INSERT INTO tmptable (invoiceid)
SELECT DISTINCT invoiceid FROM tbltaxamount';
FOR rec IN
SELECT taxname, taxamt, invoiceid FROM tbltaxamount ORDER BY invoiceid
LOOP
EXECUTE '
UPDATE tmptable
SET ' || quote_ident(lower(replace(rec.taxname,' ','_')))
|| ' = '|| rec.taxamt || '
WHERE invoiceid = ' || rec.invoiceid;
END LOOP;
END;
$BODY$ LANGUAGE plpgsql;
Это работает для PostgreSQL 9.1 или новее.
Для pg 8.4 или новее заменить
SELECT string_agg(col || ' numeric(9,2) DEFAULT 0', ', ')
с:
SELECT array_to_string(array_agg(col || ' numeric(9,2) DEFAULT 0'), ', ')
Для версий даже более старых , чем те, которые создают агрегатную функцию, например:
CREATE OR REPLACE FUNCTION f_concat_comma(text, text)
RETURNS text AS
$BODY$
BEGIN
RETURN ($1 || ', '::text) || $2;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
CREATE AGGREGATE concat_comma(text) (
SFUNC=f_concat_comma,
STYPE=text
);
А потом напишите:
SELECT concat_comma(col || ' numeric(9,2) DEFAULT 0')
Также:
DROP TABLE IF EXISTS tmptable;
Пункт "ЕСЛИ СУЩЕСТВУЕТ" был введен с версией 8.2 .
Если вам нужна версия , даже старше , чем вы можете:
IF EXISTS (
SELECT *
FROM pg_catalog.pg_class
WHERE oid = 'tmptable'::regclass
AND relkind = 'r')
THEN
DROP TABLE tmptable;
END IF;
*/
Обновление!
Ознакомьтесь с политикой управления версиями проекта PostgreSQL . Версия 8.0.1 является особенно глючной. Я бы настоятельно посоветовал вам обновить. Если вы не можете перейти на более новую основную версию, по крайней мере, из соображений безопасности обновите ее до последней версии, 8.0.26. Это можно сделать на месте, ничего не меняя.