【问题标题】:Postgres error in creating a function创建函数时的 Postgres 错误
【发布时间】:2014-08-14 17:20:10
【问题描述】:

我正在尝试在 Postgres 中创建一个函数,如下所示:

Create function Samplefunc() 
returns resultdata( Tested int, Score int,
       Growth int) as
$BODY$
Select 
       Count(distinct student_id) Tested, 
       Cast(Avg(R.raw_score) as Int)  Score,
       Avg(R.growth) as Growth
from results R
where R.id=1 and test_id='ME04';
$BODY$
LANGUAGE sql;

但我收到以下错误:

ERROR:  syntax error at or near "int"
LINE 2: returns resultdata( NTested int, RawScore int,
                                    ^

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

ERROR: syntax error at or near "int"
SQL state: 42601
Character: 59

我哪里错了?

【问题讨论】:

    标签: sql postgresql user-defined-functions


    【解决方案1】:
    CREATE FUNCTION samplefunc() 
      RETURNS TABLE(ntested int, rawscore int, growth int) AS
    $func$
    SELECT count(DISTINCT r.student_id) -- AS NTested
          ,avg(r.raw_score)::int        -- AS RawScore
          ,avg(r.growth)::int           -- AS Growth
    FROM   reports_results r
    WHERE  r.test_type_id = 1
    AND    r.test_id = '201403MAME04'
    $func$ LANGUAGE sql;
    
    • 返回表的子句是RETURNS TABLE

    • 小心避免OUT 参数和列名之间的冲突。 (我的初稿中有这样的冲突)。表限定列以消除歧义。 RETURNS TABLE 中的所有字段名称实际上都是 OUT 参数,并且在函数内(几乎)随处可见。

    还有:

    如果保证查询返回单个行,您可能希望将OUT参数与RETURNS record结合起来:

    CREATE FUNCTION samplefunc(OUT ntested int, OUT rawscore int, OUT growth int) 
      RETURNS record  AS ...
    

    细微的差别:这样一来,如果没有找到任何内容,您将获得带有 NULL 值的单行,而第一个表单将不返回任何内容/没有行。

    添加 IN 参数(在评论中请求)

    CREATE FUNCTION samplefunc(_test_type_id int, _test_id text) 
      RETURNS TABLE(ntested int, rawscore int, growth int) AS
    $func$
    SELECT count(DISTINCT r.student_id)
          ,avg(r.raw_score)::int
          ,avg(r.growth)::int
    FROM   reports_results r
    WHERE  r.test_type_id = $1   -- or: = _test_type_id in Postgres 9.2+
    AND    r.test_id = $2        -- or: = _test_id
    $func$ LANGUAGE sql;

    这里有很多关于 SO 的相关答案以及更多代码示例。喜欢:

    Try a search.

    【讨论】:

    • 嗨..谢谢你的回答。效果很好!我如何修改它以传递一些参数,这样我就不必像“where R.test_type_id=1 and test_id='201403MAME04';”那样定义它没有了吗?
    • @crozzfire:我为我的答案添加了另一个答案。
    • 嗨,你能帮我吗? stackoverflow.com/questions/25814827/…
    【解决方案2】:

    尽量不要指定复合返回类型的细节。但是,我认为回报结构必须首先存在。

    Create table resultdata (NTested int, RawScore int, Growth int);
    
    Create function Samplefunc() returns resultdata as
    $BODY$
    Select 
       Count(distinct student_id) as NTested, 
       Cast(Avg(R.raw_score) as Int) as RawScore,
       Avg(R.growth) as Growth
    from reports_results R
    where R.test_type_id=1 and test_id='201403MAME04';
    $BODY$
    LANGUAGE sql;
    

    或者尝试显式返回一个表:

    Create function Samplefunc() 
        returns Table (NTested int, RawScore int, Growth int) as
    $BODY$
    Select 
       Count(distinct student_id) as NTested, 
       Cast(Avg(R.raw_score) as Int) as RawScore,
       Avg(R.growth) as Growth
    from reports_results R
    where R.test_type_id=1 and test_id='201403MAME04';
    $BODY$
    LANGUAGE sql;
    

    我认为你也可以使用输出参数返回一组记录:

    Create function Samplefunc(OUT NTested int, OUT RawScore int, OUT Growth int) 
        returns SetOf Record as
    $BODY$
    Select 
       Count(distinct student_id) as NTested, 
       Cast(Avg(R.raw_score) as Int) as RawScore,
       Avg(R.growth) as Growth
    from reports_results R
    where R.test_type_id=1 and test_id='201403MAME04';
    $BODY$
    LANGUAGE sql;
    

    【讨论】:

      【解决方案3】:

      您正在尝试返回包含多个输出参数的记录。你应该这样做:

      Create function Samplefunc(out NTested int, out RawScore int, out Growth int) as
      $BODY$
      Select 
             Count(distinct student_id) NTested, 
             Cast(Avg(R.raw_score) as Int)  RawScore,
             Avg(R.growth) as Growth
      from reports_results R
      where R.test_type_id=1 and test_id='201403MAME04';
      $BODY$
      LANGUAGE sql;
      

      您可以使用显式命名的复合类型更详细地执行相同的操作;喜欢

      CREATE TYPE resultdata AS (NTested int, RawScore int, Growth int);
      
      CREATE FUNCTION Samplefunc() RETURNS resultdata
          AS .......
      

      或使用TABLE 之类的函数

      CREATE FUNCTION Samplefunc() RETURNS TABLE(NTested int, RawScore int, Growth int)
      AS
      ......
      

      有关更多信息,请参阅PostgreSQL Documentation

      【讨论】:

        【解决方案4】:

        如果您没有像 Luke 正确假设的那样定义类型“结果集”,请尝试返回一个表。

        Create function Samplefunc() 
        returns table( NTested int, RawScore int,
               Growth int) as
        $BODY$
        Select 
               Count(distinct student_id) NTested, 
               Cast(Avg(R.raw_score) as Int)  RawScore,
               Avg(R.growth) as Growth
        from reports_results R
        where R.test_type_id=1 and test_id='201403MAME04';
        $BODY$
        LANGUAGE sql;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-14
          • 2013-06-15
          • 2017-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-23
          相关资源
          最近更新 更多