创建函数时的 Postgres 错误
Posted
技术标签:
【中文标题】创建函数时的 Postgres 错误【英文标题】:Postgres error in creating a function 【发布时间】: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
我哪里错了?
【问题讨论】:
【参考方案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
参数,并且在函数内(几乎)随处可见。
还有:
avg(growth)
将导致类型与声明的返回类型 int
不匹配。你也需要投射它。使用简短的Postgres-specific syntax ::type
,顺便说一句。
更好的是:返回 numeric
or a floating point number 以保留平均数字中的小数位数。
列别名仅在函数内部可见。如果您不打算在函数内部引用它们,它们只是文档。
大写是怎么回事? Unquoted identifiers are cast to lower case in Postgres automatically.
如果保证查询返回单个行,您可能希望将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 的相关答案以及更多代码示例。喜欢:
PostgreSQL return a function with a Custom Data TypeTry a search.
【讨论】:
嗨..谢谢你的回答。效果很好!我如何修改它以传递一些参数,这样我就不必像“where R.test_type_id=1 and test_id='201403MAME04';”那样定义它没有了吗? @crozzfire:我为我的答案添加了另一个答案。 嗨,你能帮我吗? ***.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;
【讨论】:
以上是关于创建函数时的 Postgres 错误的主要内容,如果未能解决你的问题,请参考以下文章