2014-03-13 190 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:谢谢,修复。 –