您的解决方案是可行的。我为了简化/提高性能/易读性/安全性而大量重写了您的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;
“IF EXISTS”子句是在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。这可以在原地完成,不需要更改任何其他内容。
code
ERROR: 找不到数据类型为record的数组类型 CONTEXT: SQL语句 "SELECT 'CREATE TABLE tmptable (invoiceid integer PRIMARY KEY, ' || ( SELECT ( col || ' numeric(9,2) DEFAULT 0', ', ' ) FROM ( SELECT lower(replace(taxname,' ','_')) AS col FROM tbltaxamount GROUP BY 1 ORDER BY 1 ) x ) || ')'" PL/pgSQL函数"f_taxamount"第12行执行语句 - Bhavik Ambani