Giải pháp của bạn là một cách khả thi. Phần lớn tôi đã viết lại hàm plpgsql của bạn để đơn giản hóa / hiệu suất / khả năng đọc / bảo mật.
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;
Điều này hoạt động cho PostgreSQL 9.1 trở lên.
Đối với pg 8.4 hoặc sau đó thay thế
SELECT string_agg(col || ' numeric(9,2) DEFAULT 0', ', ')
với:
SELECT array_to_string(array_agg(col || ' numeric(9,2) DEFAULT 0'), ', ')
Đối với các phiên bản thậm chí cũ hơn hơn là tạo một hàm tổng hợp như thế này:
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
);
Và sau đó viết:
SELECT concat_comma(col || ' numeric(9,2) DEFAULT 0')
Ngoài ra:
DROP TABLE IF EXISTS tmptable;
Mệnh đề "NẾU TỒN TẠI" đã được giới thiệu với phiên bản 8.2 .
Nếu bạn nên sử dụng phiên bản thậm chí cũ hơn hơn những gì bạn nên làm:
IF EXISTS (
SELECT *
FROM pg_catalog.pg_class
WHERE oid = 'tmptable'::regclass
AND relkind = 'r')
THEN
DROP TABLE tmptable;
END IF;
*/
Nâng cấp!
Hãy xem chính sách lập phiên bản của dự án PostgreSQL . Phiên bản 8.0.1 là một phiên bản đặc biệt có nhiều lỗi. Tôi sẽ mạnh mẽ khuyên bạn nên nâng cấp. Nếu bạn không thể nâng cấp lên phiên bản chính mới hơn, ít nhất hãy nâng cấp lên bản phát hành điểm mới nhất vì lý do bảo mật, 8.0.26 trong trường hợp của bạn. Điều này có thể được thực hiện tại chỗ mà không cần thay đổi bất kỳ điều gì khác.