如何使用pl / pgSQL处理“逗号分隔列表”返回?

时间:2019-01-09 05:09:10

标签: sql postgresql plpgsql

我正在尝试UNION ALL到新表中的许多表。旧表的列是相同的,但列的顺序是不同的,因此下面的SQL语句将得到错误的结果:

CREATE TABLE sum_7_2018_xia_weijian
AS
(
        SELECT * FROM huiwen
        UNION
        SELECT * FROM penglai
        UNION
        SELECT * FROM baoluo
        UNION
        SELECT * FROM dongge
        UNION
        SELECT * FROM resultdonglu
        UNION
        SELECT * FROM resultwencheng
        UNION
        SELECT * FROM tan_illeg
);

我终于纠正了它,但是SQL语句太多余了:

步骤1.获取名为huiwen的旧表之一的列名。

SELECT string_agg(column_name, ',')
                FROM information_schema.columns
                WHERE table_schema = 'public' AND table_name   = 'huiwen';

结果:

>                                      string_agg                                     
> ----------------------------------------------------------------------
>
>  gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx

步骤2.将表合并为新表。我将表string_agg的{​​{1}}复制到每个SELECT-UNION以保持列的顺序,这很笨拙。

huiwen

结果:

CREATE TABLE sum_2018_xia_weijian
AS
(
        SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
        FROM huiwen
        UNION ALL
        SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
        FROM penglai
        UNION ALL
        SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
        FROM baoluo
);

我尝试通过使用变量> Query returned successfully: 2206 rows affected, 133 msec execution time. pl/pgSQL进行一些优化来处理列名,但是未能找到任何SQL数据类型可以处理此问题。使用Declarations结果RECORD

Pseudo-Types ERROR

2 个答案:

答案 0 :(得分:1)

除了使编程块变得复杂之外,您还可以遵循Union或Union All文档中的以下一些概念:

  1. 所有查询中的列数必须相同。
  2. 相应的列必须具有兼容的数据类型。
  3. 第一个查询的列名确定组合结果集的列名。
  4. GROUP BY和HAVING子句应用于每个单独的查询,而不是最终结果集。
  5. ORDER BY子句应用于组合的结果集,而不是在单个结果集中。

在第3点之后,对您的Union查询进行调整,使其引用结果中预期列顺序的表。

答案 1 :(得分:1)

您可以两次使用STRING_AGG来获取UNION ALL。您可以通过column_name中的string_agg对其进行显式排序来按特定顺序获取所有列。

这是一个通用函数,它需要一个表数组和一个最终表名。

CREATE or replace FUNCTION fn_create_tab(tname_arr TEXT[], p_tab_name TEXT) 
RETURNS VOID AS $$
DECLARE
l_select TEXT;
BEGIN
   select STRING_AGG(query,' UNION ALL ' ) INTO l_select
    FROM
    (
     SELECT 'select ' || string_agg( column_name,','
     ORDER BY column_name ) || ' from ' || table_name as query
       FROM information_schema.columns
      WHERE table_schema = 'public' AND table_name = ANY (tname_arr)
     GROUP BY table_name
     ) s;

 IF l_select IS NOT NULL
  THEN
    EXECUTE format ('DROP TABLE IF EXISTS %I',p_tab_name);
    EXECUTE format ('create table %I  AS %s',p_tab_name,l_select);
  END IF;    
END;
$$ LANGUAGE plpgsql;

现在,运行如下函数:

select fn_create_tab(ARRAY['huiwen','penglai'],'sum_2018_xia_weijian');