2014-03-13 189 views
1

我現在有一個包含52個字段的表,但它會增長,並且我正在嘗試編寫一個動態INSERT語句,它將填充字段0而不必指定52 0。將逗號分隔的字符串拆分爲列

這是表的一個簡化版本:

CREATE TABLE tbladmin_reportsettings 
(
    intreportsettingsid integer NOT NULL, 
    strReportGroup character varying (20) NOT NULL, 
    ysnExcludePax1 smallint DEFAULT NULL, 
    ysnExcludePax3 smallint DEFAULT NULL, 
    ysnExcludePax2 smallint DEFAULT NULL, 
    ysnExcludePax4 smallint DEFAULT NULL, 
    ysnExcludePax5 smallint DEFAULT NULL, 
    ysnHideAgentABN smallint DEFAULT NULL, 
CONSTRAINT pk_tbladmin_reportsettings PRIMARY KEY (intreportsettingsid) 
) 

的INSERT腳本是:

INSERT INTO tblAdmin_ReportSettings 
VALUES 
((select * from getautonumber('ReportSettingsID')),'Base',0,0,0,0,0); 

的DEFAULT NULL列上是故意的,所以我不能簡單地改變那麼爲0.

我可以得到一串足夠的'0'重複來填充插入的其餘部分:

select string_agg(0::text,','::text) from information_schema.columns 
WHERE table_name = 'tbladmin_reportsettings' 
AND column_name NOT IN('intreportsettingsid', 'strreportgroup') 

但它將string_agg全部作爲一個字段 - 我需要將它們分成單獨的字段。

這是我的嘗試:

INSERT INTO tblAdmin_ReportSettings 
VALUES 
(select (select * from getautonumber('ReportSettingsID')),'Base', 
     trim(string_agg('0',','),',') 
from information_schema.columns 
WHERE table_name = 'tbladmin_reportsettings' 
AND column_name NOT IN('intreportsettingsid', 'strreportgroup') 
) 

但輸出是:的

column1 | column2 | column3 
29 | Base | 0,0,0,0,0 

代替

column1 | column2 | column3 | column4 | column5 | column6 | column7 
29 | Base | 0 | 0 | 0 | 0 | 0 

我曾嘗試創建一個數組和UNNEST()它,但結果是多行而不是多列。

有人可以請建議一個語法或函數,可能會得到這個工作嗎?

+4

這是一個不好的設計。你不需要在一行中擁有所有的屬性,只能有4個:'intreportsettingsid','strReportGroup','attributeName','attributeValue'。例如。 '29 |基地| column3 | 0','29 |基地| column4 | 0'等 – Alexander

+0

@Alexander:這可能是糟糕的設計。但是你基本上沒有通過這個判斷。如果所有列都已填滿,則建議的設計大約需要25倍的磁盤空間。如果大多數列保持爲空(0),那麼您的模型會變得更具吸引力...... –

回答

2

你需要動態SQL。在DO statement或PLPGSQL功能使用EXECUTE

DO 
$do$ 
BEGIN 

EXECUTE (
SELECT 'INSERT INTO t1 (intreportsettingsid,strReportGroup,' 
     || string_agg(column_name, ',') || $$) 
VALUES (getautonumber('ReportSettingsID'),'Base',$$ 
     || string_agg('0', ','::text) || ')' 
FROM information_schema.columns 
WHERE table_name = 'tbladmin_reportsettings' 
AND table_aschema = 'public'   -- table name might not be unique! 
AND column_name NOT IN('intreportsettingsid', 'strreportgroup') 
); 

END 
$do$; 
+0

這正是我所追求的 - 謝謝!只需要在最後一行添加一個額外的「)」:'AND column_name NOT IN('intreportsettingsid','strreportgroup'));' – simon86

+0

@ simon86:謝謝,修復。 –