【问题标题】:Error when creating plpgsql function with if then statement使用 if then 语句创建 plpgsql 函数时出错
【发布时间】:2013-12-16 20:45:46
【问题描述】:

我正在尝试创建这个 PostgreSQL 函数:

create or replace function sp_get_user_activity(
        begindate date = null,
    enddate date = null)
returns table ( 
    page varchar(75)) as
$body$
begin
    return query
    if begindate is not null and enddate is not null then
        begin
        select page from log_pg where begindate >= created and endate <= created;
        end;
    else
        if begindate is not null then
            begin
            select page from log_pg where begindate >= la.created_on;
            end;
        end if;
        if enddate is not null then
            begin
            select page from log_pg where endate <= created;
            end;
        end if;
    end if;
end;
$body$
language plpgsql;

我想创建一个从表中获取页面名称的函数,该函数可以不包括开始日期和结束日期,或者只是一个结束日期或只是一个开始日期。

我在尝试创建函数时收到的错误消息是并且指的是第一个“if”语句(我在上面剪切/粘贴的代码中的第 9 行)

ERROR:  syntax error at or near "if"
LINE 14:  if begindate is not null and enddate is not null then
          ^

********** Error **********

ERROR: syntax error at or near "if"
SQL state: 42601

尝试谷歌搜索错误代码但没有成功。

【问题讨论】:

    标签: sql function postgresql if-statement plpgsql


    【解决方案1】:
    CREATE OR REPLACE FUNCTION sp_get_user_activity(begindate date = null
                                                   ,enddate   date = null)
    RETURNS TABLE (page varchar(75)) AS
    $func$
    BEGIN
    
    IF begindate IS NOT NULL AND enddate IS NOT NULL THEN
       RETURN QUERY
       SELECT l.page FROM log_pg l WHERE l.created BETWEEN begindate AND enddate;
    
    ELSIF begindate IS NULL THEN
       RETURN QUERY
       SELECT l.page from log_pg l where l.created >= enddate;
    
    ELSE
       RETURN QUERY
       SELECT l.page FROM log_pg l WHERE l.created <= begindate;
    END IF;
    
    END
    $func$ LANGUAGE plpgsql;
    
    • RETURN QUERY 必须后跟 SELECT 语句。您不能改用 IF 块。这是错误消息的直接原因。

    • 不要在没有需要的情况下启动单独的代码块 (begin .. end;)。它们具有成本性能并吃掉交易ID。在 plpgsql 中几乎没有必要。

    • 简化您的逻辑。如果IS NULL两者之一,您可以简化..

    • endatecreated_on 中的错别字。 la.created_on中的非法表限定。

    • 必须对可能与参数名称冲突的列名进行表限定 (SELECT l.page FROM log_pg l ...)。您的OUT 参数page 在函数体中随处可见。会与列名page 冲突。作为替代方案,您可以避免参数名称冲突。

    这个单一的 SQL 语句会做同样的事情,顺便说一句:

    SELECT page FROM log_pg
    WHERE (begindate >= created OR begindate IS NULL)
    AND   (enddate <= created OR enddate IS NULL);
    

    您可以将其包装到另一个 plpgsql 函数或简单的 SQL 函数中:

    CREATE OR REPLACE FUNCTION sp_get_user_activity(begindate date = null
                                                   ,enddate   date = null)
      RETURNS SETOF varchar(75) AS
    $func$
    SELECT page FROM log_pg
    WHERE (begindate >= created OR begindate IS NULL)
    AND   (enddate <= created OR enddate IS NULL)
    $func$ LANGUAGE sql;
    

    需要 Postgres 9.1 或更高版本。在旧版本中,您必须在 SQL 函数中使用位置参数($1$2)。

    【讨论】:

    • 非常感谢 erwin 的反馈。你的方法更干净。
    【解决方案2】:

    以下行有问题:

    return query        
    

    如果你删除它,它会修复错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-11
      • 1970-01-01
      • 2015-11-18
      • 1970-01-01
      相关资源
      最近更新 更多