【问题标题】:Dynamic column in SELECT statement postgresSELECT 语句 postgres 中的动态列
【发布时间】:2011-01-23 09:32:54
【问题描述】:

我对 postgresql 很陌生。

实现这一目标的最佳方法是什么?

SELECT get_columns() 
  FROM table_name;

get_columns() 将为查询提供列名。我看到有人建议使用 EXECUTE 语句,但我无法使用。

假设有一个包含 a、b、c 列的表 Test 我想跑

SELECT a,b FROM Test;
SELECT a,c FROM Test;

动态生成列名。

【问题讨论】:

  • 有什么意义?如果您不知道列名,只需在查询中使用 *。也许我错过了什么?
  • 他所说的是get_columns() 将返回任一ac 或列ab。他不想要所有列,只想要程序生成的列。
  • 这个想法是 get_columns() 将接受一些参数,因此将返回适当的列以在某处使用。当处理 COPY FROM 命令时,这篇文章将很有用,我需要根据我选择的 csv 文件提供列名。
  • 但是如果您知道函数的参数,为什么不知道列名?您可以获得列名,没问题,但如果您已经知道它们(请参阅参数),则无需再次获取它们。
  • 让我在这里谈谈我的用例。我们运行一个项目,嵌入式设备将文件发送到我们的服务器。有 3-4 种类型的设备,每种类型都有多个版本号。每个设备发送一个 csv 文件,每行大约 150 个条目,每个设备列略有变化。我们有每种设备类型的表格(我将从其中提取列名)。我需要使用 COPY FROM 将这些文件导入一个巨大的表(一个用于所有设备)我不想为每种类型的设备文件列出 9 个不同的 COPY FROM 命令。我需要一种更简洁的方式来完成这一切。

标签: sql postgresql


【解决方案1】:

要编写动态查询,您必须执行以下操作:

EXECUTE 'SELECT '|| get_columns()|| ' FROM table_name' INTO results

请阅读文档: http://developer.postgresql.org/pgdocs/postgres/plpgsql-statements.html

【讨论】:

  • 如何查询动态表名?如SELECT * FROM (select table_name from XXX where id = 1);
【解决方案2】:

在这种情况下,我会使用PL/pgSQL function using cursor

【讨论】:

    【解决方案3】:

    由于您使用 COPY FROM 到已知的大表,因此创建一个返回 SETOF bigtable 并从特定类型中选择所有列的 FUNCTION,对特定情况下不需要的字段使用 NULL AS 字段名,例如:

    # \d SMALL
         Table "public.small"
     Column |  Type   | Modifiers 
    --------+---------+-----------
     a      | integer | 
     b      | integer | 
     c      | integer | 
     d      | integer | 
    
    # \d LARGE
         Table "public.large"
     Column |  Type   | Modifiers 
    --------+---------+-----------
     a      | integer | 
     b      | integer | 
     c      | integer | 
     d      | integer | 
    
    # CREATE OR REPLACE FUNCTION myData()
     RETURNS SETOF large LANGUAGE SQL AS $$
    SELECT a, 
           CASE WHEN a = 1 
                THEN b 
           ELSE 
                NULL 
    END as b, 
           CASE WHEN a = 2 
                THEN c 
           ELSE 
                NULL
    END AS c, 
    d
    FROM small;
    $$;
    
    # SELECT * FROM mydata();
    # COPY (SELECT * FROM myData()) TO STDOUT;
    

    显然 SQL 可能不是最好使用的语言,因此 PL/PgSQL 或 PL/Perl(或其他)可能是合适的。

    【讨论】:

    • 这似乎是错误的方式,随意忽略这个答案
    【解决方案4】:

    您将无法使用函数来生成列列表。而且我真的不认为这是解决问题的最佳方法...也就是说,您可以像这样使用 8.4 来做到这一点:

    创建或替换函数 dyn(p_name VARCHAR)
    返回记录为
    $$
      宣布
        p_sql 文本;
      开始
       选择“选择”||
         CASE p_name WHEN 'foo' THEN ' col1, col2, col3, col4 '
          当'bar'然后'col3,col4,col5,col6'
          当'baz'然后'col1,col3,col4,col6'结束||
       '来自我的测试'
       进入 p_sql;
       返回查询执行 p_sql;
      结尾
    $$ LANGUAGE 'plpgsql';

    用法如下: SELECT * FROM dyn('foo') AS (一整型,二整型,三整型,四整型)

    但老实说,我建议只为每个设备制作一个视图。

    【讨论】:

    • @ChrisTravers:该行只是将脚本连接到p_sql。它执行得更远。
    • 啊,我明白了。有什么理由不只做 RETURN QUERY EXECUTE 'SELECT...'?
    【解决方案5】:

    我认为您最大的问题是您需要以 PostgreSQL 可以理解的方式返回行。这基本上意味着,您可以返回一个 refcursor,或者您可以返回一组一致的数据类型。我更喜欢后者,因为从编程的角度来看,它使系统更加一致,并且您可以采取一些高级方向,但我也可以看到另一种方式。

    【讨论】:

      猜你喜欢
      • 2017-09-26
      • 2013-11-27
      • 2021-01-28
      • 2013-06-30
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      相关资源
      最近更新 更多