如何用pl/pgSQL来处理'comma separated list'returns?

How to use pl/pgSQL to handle 'comma separated list' returns?

我正在尝试 UNION ALL 将许多 table 放入新的 table.The 列中,旧 table 的列是相同的,但列的顺序是不同,所以下面的 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

的旧 table 之一的列名称
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 步。将 table 合并为一个新的 table。我将 table huiwenstring_agg 复制到每个 SELECT-UNION 以保持列的顺序,这很笨拙。

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 使用 Declarations 变量来处理列名来进行一些优化,但未能找到任何 SQL 数据类型可以处理此问题。使用RECORD结果Pseudo-Types ERROR

CREATE or replace FUNCTION ct() RETURNS RECORD AS $$
DECLARE
    clms RECORD;
BEGIN
    SELECT column_name INTO clms
        FROM information_schema.columns
        WHERE table_schema = 'public' AND table_name = 'huiwen';
    RETURN clms;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE sum_2018_xia_weijian
AS
(
    SELECT ct() FROM huiwen
    UNION ALL
    SELECT ct() FROM penglai
    UNION ALL
    SELECT ct() FROM baoluo
    UNION ALL
    SELECT ct() FROM dongge
    UNION ALL
    SELECT ct() FROM resultdonglu
    UNION ALL
    SELECT ct() FROM resultwencheng
    UNION ALL
    SELECT ct() FROM tan_illeg
);

您可以遵循 Union 或 Union All 文档中的以下一些概念,而不是使编程块变得复杂:

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

按照第 3 点,将您的联合查询调整为引用 table,其列顺序在结果中是预期的。

您可以使用 STRING_AGG 两次以获得 UNION ALL。您可以通过 string_agg.

中的 column_name 显式排序来按特定顺序获取所有列

这是一个通用函数,它采用 table 数组和最终的 table 名称。

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');