【问题标题】:PostgreSQL: How to use SELECT statement within CASE expression in function?PostgreSQL:如何在函数的 CASE 表达式中使用 SELECT 语句?
【发布时间】:2014-04-01 03:55:42
【问题描述】:

我们可以在函数的 CASE 条件表达式中使用 SELECT 语句吗?
我尝试了以下功能来完成上述任务。

示例:我有一个函数用于显示包含一些行的表格。

create or replace function test(n integer) 
returns table (name text,city text) as
$body$
begin
     case n when 1 then
     select * from table1

     when 2 then
     select * from table2

     when 3 then
     select * from view1

     end;
end;
$body$
language plpgsql;

--调用函数

select * from test(1);  
/*have to show details of table1*/

select * from test(2);
/*have to show details of table2*/

select * from test(3);
/*have to display details of view1*/

【问题讨论】:

    标签: postgresql case plpgsql


    【解决方案1】:

    其实有一个plpgsql CASE statement,不要和SQL CASE expression混淆:

    CREATE OR REPLACE function test(n integer) 
      RETURNS TABLE (name text, city text) AS
    $func$
    BEGIN
    
    CASE n
    WHEN 1 THEN
        RETURN QUERY SELECT t.name, t.city FROM table1 t;
    WHEN 2 THEN
        RETURN QUERY SELECT t.foo, t.bar   FROM table2 t;
    WHEN 3 THEN
        RETURN QUERY SELECT t.bar, t.bamm  FROM view1 t;
    END CASE;
    
    END
    $func$ LANGUAGE plpgsql;
    
    • 如果您将函数声明为 RETURNS TABLE (name text, city text),那么您的 SELECT 语句应该有一个匹配类型的列列表。
      另一方面,如果您想SELECT *,请相应地将函数声明为RETURNS SETOF table1。

    • 在返回类型中命名列时,这些变量在函数体中可见。确保对可能与相同名称冲突的列名进行表限定。所以t.name 而不仅仅是name。

    • 函数内部查询的列名在外部不可见。只有声明的返回类型。所以名称不必匹配,只需匹配数据类型即可。

    无论哪种方式,我建议简化一些事情:

    CREATE OR REPLACE function test(n integer) 
      RETURNS SETOF table1 AS
    $func$
    
    SELECT * FROM table1 t WHERE n = 1
    UNION ALL
    SELECT * FROM table2 t WHERE n = 2
    UNION ALL
    SELECT * FROM view1  t WHERE n = 3;
    
    $func$ LANGUAGE sql;
    

    同样的结果。一样快。 SQL 或 PL/pgSQL 函数是个人喜好和其他一些细节问题。 PL/pgSQL 对于独立调用可能更快。 SQL 更容易嵌套。

    【讨论】:

    • 非常感谢。这里有点混乱。 UNION ALL 需要所有列都相同,但是当我想显示一个具有不同列的表时,这里可以吗?
    • @Meem:列的number 和它们的日期类型 必须匹配(或者可以在密切相关的类型之间进行自动转换)。或者您必须填写常量并进行强制转换以使它们匹配。函数也是如此。对于UNION 查询,仅使用第一段的名称,UNION 查询的后面段中的名称并非无关紧要。对于该函数,仅使用声明的 RETURN 类型的名称。
    【解决方案2】:

    为此,您需要一个IF 声明和RETURN QUERY,例如

    create or replace function test(n integer) 
    returns table (name text,city text) as
    $body$
    begin
         IF n = 1 THEN
             RETURN QUERY select * from table1;
         ELIF n = 2 THEN
             RETURN QUERY select * from table2;
         ELIF n = 3 THEN
             RETURN QUERY select * from view1;
         END IF;
    end;
    $body$
    language plpgsql;
    

    不过,这是一件非常奇怪的事情。

    【讨论】:

    • 还有一个问题,如果我想显示与上面返回表具有不同列名的 table2 行,那么如何显示它。
    • 如果您想问其他问题,请发布一个新问题; Stack Overflow 尝试在每个问题上停留在一个主要主题上。
    • 好的,会处理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 2016-05-02
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    相关资源
    最近更新 更多