PostgreSQL选择OUT变量

时间:2017-05-09 05:59:17

标签: postgresql postgresql-9.6

这是我之前提出的问题的第二次迭代。我正在创建以下功能。

CREATE FUNCTION public.getpogstats(IN symbol character varying, IN pogtypeid integer, OUT closehi numeric, OUT closelo numeric, OUT dayhi numeric, OUT daylo numeric, OUT s7dhi numeric, OUT s7dlo numeric, OUT t13hi numeric, OUT t13lo numeric, OUT close numeric, OUT firstdate timestamp without time zone)
    RETURNS record
    LANGUAGE 'sql'

AS $function$
SELECT ROUND(MAX(closeprice), 2), ROUND(MIN(closeprice), 2), ROUND(MAX(dayhigh), 2), ROUND(MIN(daylow), 2), ROUND(MAX(sevendaydp), 2), ROUND(MIN(sevendaydp), 2),
    ROUND(MAX(thirteendaydp), 2), ROUND(MIN(thirteendaydp), 2), MIN(datadate) 
    INTO closehi, closelo, dayhi, daylo, s7dhi, s7dlo, t13hi, t13lo, firstdate
FROM pogdata
JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = pogtypeid
WHERE symbol.symbol = symbol;

SELECT ROUND(closeprice, 2) INTO close FROM pogdata
JOIN symbol ON pogdata.symbolid = symbol.symbolid
WHERE datadate = (SELECT MAX(datadate) 
                  FROM pogdata JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = pogtypeid 
                  WHERE symbol.symbol = symbol)
AND symbol.symbol = symbol;

$function$;

ALTER FUNCTION public.getpogstats(character varying, integer)
    OWNER TO postgres;

当我执行创建此功能时,我收到以下消息:

ERROR:  syntax error at or near ","
LINE 8:     INTO closehi, closelo, dayhi, daylo, s7dhi, s7dlo, t13hi...
                        ^
********** Error **********

ERROR: syntax error at or near ","
SQL state: 42601
Character: 620

我正在尝试按照PostgreSQL上的文档说明

  

...其中target可以是记录变量,行变量或a   以逗号分隔的简单变量和记录/行字段列表。

将OUT参数计为"简单变量"?

3 个答案:

答案 0 :(得分:1)

<div id="string"> worlds and some other text </div> <button id="button" onclick="validate()">click me</button>参数是您可以在OUT语句中使用的变量。

然而,您正在混淆SQL函数和PL / pgSQL函数。

您声明函数(SELECT ... INTO)的方式如下:

  • 它只能包含常规SQL语句(例如,没有LANGUAGE 'sql'),最后一个语句的结果是函数的结果(参见the documentation)。

  • Output parameters仅提供上一个SELECT ... INTO语句的结果列的名称。

您需要的是PL / pgSQL函数(SELECT)。

然后你可以使用LANGUAGE 'plpgsql',但你必须将你的代码安排到PL / pgSQL块中:

SELECT ... INTO

答案 1 :(得分:1)

如果您愿意,可以将其保留为SQL函数。 SQL函数可以通过运行多个SELECT查询返回多个,但它们只能从同一查询返回多个列。因此,为了保持SQL函数,您需要使用返回所有列的单个查询。这可以通过公用表表达式来实现:

CREATE FUNCTION public.getpogstats(IN p_symbol character varying, IN p_pogtypeid integer, OUT closehi numeric, OUT closelo numeric, OUT dayhi numeric, OUT daylo numeric, OUT s7dhi numeric, OUT s7dlo numeric, OUT t13hi numeric, OUT t13lo numeric, OUT close numeric, OUT firstdate timestamp without time zone)
    RETURNS record
    LANGUAGE sql
AS $function$
  with data1 as (
    SELECT ROUND(MAX(closeprice), 2) as closehi, 
           ROUND(MIN(closeprice), 2) as closelo, 
           ROUND(MAX(dayhigh), 2) as dayhi, 
           ROUND(MIN(daylow), 2) as daylo, 
           ROUND(MAX(sevendaydp), 2) as s7dhi, 
           ROUND(MIN(sevendaydp), 2) as s7dlo,
           ROUND(MAX(thirteendaydp), 2) as t13hi, 
           ROUND(MIN(thirteendaydp), 2) as t13lo, 
           MIN(datadate) as firstdate
    FROM pogdata
      JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = p_pogtypeid
    WHERE symbol.symbol = p_symbol
  ), data2 as (
    SELECT ROUND(closeprice, 2) as close
    FROM pogdata
      JOIN symbol ON pogdata.symbolid = symbol.symbolid
    WHERE datadate = (SELECT MAX(datadate) 
                      FROM pogdata 
                        JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = p_pogtypeid 
                      WHERE symbol.symbol = p_symbol)
    AND symbol.symbol = p_symbol
    LIMIT 1 -- just to be sure
  )
  select d1.closehi, d1.closelo, d1.dayhi, d1.daylo, d1.s7dhi, d1.s7dlo, d1.t13hi, d1.t13lo, d2.close, d1.firstdate
  from data1 as d1
    cross join data2 as d2;

$function$;

(我的印象是两个查询可以组合成一个,但现在我想不出办法做到这一点)

请注意,如果您希望结果包含多个列(而不是一个包含多个字段的列),则需要显式扩展这些列。

以下选择:

select getpogstats('foo', 1);

将返回包含多个字段的单个列的单行,如:

getpogstats
-----------
(1,2,3,4,5,6,7,8,9,"2017-05-09 18:19:20")

因为该函数被声明为“RETURNS记录”。

但是,如果您希望将结果作为单个列,则需要使用:

select (getpogstats('foo', 1)).*;

然后你将分别得到每一列:

closehi | closelo | dayhi | ...
--------+---------+-------+----
      1 |       2 |     3 | ...

通常,如果将它们声明为returns table (...),则返回多个列的函数更容易处理:

CREATE FUNCTION public.getpogstats(p_symbol character varying, p_pogtypeid integer)
  returns table(closehi numeric, closelo numeric, dayhi numeric, daylo numeric, s7dhi numeric, s7dlo numeric, t13hi numeric, t13lo numeric, close numeric, firstdate timestamp without time zone)
  LANGUAGE sql
AS $function$
  with data1 as (
    SELECT ROUND(MAX(closeprice), 2) as closehi, 
           ROUND(MIN(closeprice), 2) as closelo, 
           ROUND(MAX(dayhigh), 2) as dayhi, 
           ROUND(MIN(daylow), 2) as daylo, 
           ROUND(MAX(sevendaydp), 2) as s7dhi, 
           ROUND(MIN(sevendaydp), 2) as s7dlo,
           ROUND(MAX(thirteendaydp), 2) as t13hi, 
           ROUND(MIN(thirteendaydp), 2) as t13lo, 
           MIN(datadate) as firstdate
    FROM pogdata
      JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = p_pogtypeid
    WHERE symbol.symbol = p_symbol
  ), data2 as (
    SELECT ROUND(closeprice, 2) as close
    FROM pogdata
      JOIN symbol ON pogdata.symbolid = symbol.symbolid
    WHERE datadate = (SELECT MAX(datadate) 
                      FROM pogdata 
                         JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = p_pogtypeid 
                      WHERE symbol.symbol = p_symbol)
    AND symbol.symbol = p_symbol
    LIMIT 1 -- just to be sure
  )
  select d1.closehi, d1.closelo, d1.dayhi, d1.daylo, d1.s7dhi, d1.s7dlo, d1.t13hi, d1.t13lo, d2.close, d1.firstdate
  from data1 as d1
    cross join data2 as d2;

$function$;

然后你可以使用:

select *
from getpogstats('foo', 1);

,结果将自动具有“表格式”结构。

答案 2 :(得分:0)

我只需更改语言并将BEGIN和END包装器添加到以下内容并且一切正常。好吧,它的工作达到了我可以执行程序的程度。谢谢你的帮助。

CREATE FUNCTION public.getpogstats(IN symbol character varying, IN pogtypeid integer, OUT closehi numeric, OUT closelo numeric, OUT dayhi numeric, OUT daylo numeric, OUT s7dhi numeric, OUT s7dlo numeric, OUT t13hi numeric, OUT t13lo numeric, OUT close numeric, OUT firstdate timestamp without time zone)
    RETURNS record
    LANGUAGE 'plpgsql'

AS $function$
BEGIN
SELECT ROUND(MAX(closeprice), 2), ROUND(MIN(closeprice), 2), ROUND(MAX(dayhigh), 2), ROUND(MIN(daylow), 2), ROUND(MAX(sevendaydp), 2), ROUND(MIN(sevendaydp), 2),
    ROUND(MAX(thirteendaydp), 2), ROUND(MIN(thirteendaydp), 2), MIN(datadate) 
    INTO closehi, closelo, dayhi, daylo, s7dhi, s7dlo, t13hi, t13lo, firstdate
FROM pogdata
JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = pogtypeid
WHERE symbol.symbol = symbol;

SELECT ROUND(closeprice, 2) INTO close FROM pogdata
JOIN symbol ON pogdata.symbolid = symbol.symbolid
WHERE datadate = (SELECT MAX(datadate) 
                  FROM pogdata JOIN symbol ON pogdata.symbolid = symbol.symbolid AND pogdata.pogtypeid = pogtypeid 
                  WHERE symbol.symbol = symbol)
AND symbol.symbol = symbol;
END;
$function$;

ALTER FUNCTION public.getpogstats(character varying, integer)
    OWNER TO postgres;