如何将表参数传递给此函数?

时间:2015-06-30 20:43:37

标签: postgresql casting plpgsql

我有一个如此组织的功能:

create function everything(waypoints waypoint)
  returns table(node int, xy text array) as $$
BEGIN
    create view results as ...

    return query (select * from results);
END;
$$ LANGUAGE plpgsql;

我有一个表,其参数的组织方式与waypoint数据类型的结构相同。此表未明确显示类型waypoint本身。

该函数应该按原样创建,但是,我无法通过像这样传入我的表来调用它:

select everything(waypoints);

select everything(select * from temp);

但是它表示前者select或附近的语法错误,前者不存在列waypoints

我该如何处理?

2 个答案:

答案 0 :(得分:6)

在Postgres中测试的所有内容 9.4

Postgres在处理ROW类型的语法中有一些弱点。您不能直接从表(别名)转换:

SELECT w::waypoint FROM waypoints w;
ERROR:  cannot cast type waypoints to waypoint

解决方案只有一步之遥:分解子查询中的行,然后执行转换。这样,列值被分解并直接包装到新类型中,而不会转换为text并返回。无需单独列出所有列,也无需创建自定义强制转换:

SELECT (w.*)::waypoint FROM (SELECT * FROM waypoints) w;

或更短:

SELECT w.*::waypoint FROM (TABLE waypoints) w;

或更短,但是:

SELECT w::waypoint FROM (TABLE waypoints) w;

SQL Fiddle

这是更短,更快,在快速测试中使用30k行和简单类型快10倍而不是转换为text并返回。如果您有(大)jsonb列或任何复杂类型(昂贵的转换为/ text),那么差异会更大。

更重要的是,您不需要其他自定义复合(ROW)类型。每个表都已将其行自动定义为类型。只需使用现有类型waypoints而不是waypoint(如果可能的话)。那么你所需要的只是:

SELECT w FROM waypoints w;

或者,对于您的示例:

SELECT everything(t) FROM temp t;  -- using type waypoints
SELECT everything(t::waypoint) FROM (TABLE temp) t;  -- using type waypoint

旁白:

  • 表没有“参数”而是列。
  • 传递table parameter to this function,而是传递行值。这就是你按名称传递表格的方式:

    你不能直接在Postgres中“传递整个表”作为参数,没有表变量。您可以使用游标或临时表。

功能

您的函数具有无效的类型声明,并且不必要地复杂。我非常怀疑你想创建一个视图:

CREATE FUNCTION everything(_wp waypoint)  -- or use type waypoints
  RETURNS TABLE(node int, xy text[]) AS
$func$
BEGIN
   RETURN QUERY
   SELECT ...
END
$func$ LANGUAGE plpgsql;

text array不是有效语法,而是使用text[]来声明text数组。

而不是使用表/类型名称waypoints作为函数参数名称,这会让您容易出错。

如果您的案例与演示一样简单,只需使用简单的SQL函数:

CREATE FUNCTION everything(_wp waypoint)  -- or use type waypoints
  RETURNS TABLE(node int, xy text[]) AS
$func$
   SELECT ...
$func$ LANGUAGE sql;

不要引用语言名称。这是一个标识符。

答案 1 :(得分:1)

如果with(df, aggregate(Var2, list(Var1), FUN = mean)) > with(df, aggregate(Var2, list(Var1), FUN = mean)) Group.1 x 1 0 4.5 2 1 2.0 3 3 6.0 4 5 2.0 5 6 2.0 waypoint中的所有类型都可转换为temp,您可以序列化到text并从<{1}}反序列化:

text

但是,明确的构造会更清晰:

SELECT  everything(temp::text::waypoint)
FROM    temp

或创建SELECT everything((col1, col2, col3, ...)::waypoint) FROM temp

CAST