SQL函数return-type:TABLE vs SETOF记录

ma1*_*w28 23 sql postgresql sql-types return-type sql-function

返回TABLEvs 的函数和SETOF records其他所有函数之间的区别是什么.

CREATE FUNCTION events_by_type_1(text) RETURNS TABLE(id bigint, name text) AS $$
    SELECT id, name FROM events WHERE type = $1;
$$ LANGUAGE SQL STABLE;

CREATE FUNCTION events_by_type_2(text) RETURNS SETOF record AS $$
    SELECT id, name FROM events WHERE type = $1;
$$ LANGUAGE SQL STABLE;
Run Code Online (Sandbox Code Playgroud)

这些函数似乎返回相同的结果.看到这个SQLFiddle.

Dan*_*ité 18

返回时SETOF record,输出列未键入且未命名.因此,此表单不能直接在FROM子句中使用,就像它是子查询或表一样.

也就是说,在发布时:

SELECT * from events_by_type_2('social');
Run Code Online (Sandbox Code Playgroud)

我们收到此错误:

错误:返回"记录"的函数需要列定义列表

它可以由SQL调用者"转换"为正确的列类型.这个表格确实有效:

SELECT * from events_by_type_2('social') as (id bigint, name text);
Run Code Online (Sandbox Code Playgroud)

并导致:

 id |      name      
----+----------------
  1 | Dance Party
  2 | Happy Hour
 ...

因此,这SETOF record被认为不太实际.只有在事先不知道结果的列类型时才应该使用它.

  • @MattDiPasquale:我不知道任何性能差异。但是,在这两种情况下,如果在更复杂的查询中使用这些函数,您可能会对[如何在SQL查询中避免使用(func())。*语法的多个函数进行评估?](http://stackoverflow.com/问题/ 18369778) (2认同)

Pet*_*uss 9

这个答案只是为了记住TABLESETOF等价的替代上下文.

正如@a_horse_with_no_name指出的那样,它不是RETURNS SETOF"未知记录",是已定义的记录.


在这个例子中,类型tablesetof等价,

CREATE TYPE footype AS (score int, term text);

CREATE FUNCTION foo() RETURNS SETOF footype AS $$
   SELECT * FROM ( VALUES (1,'hello!'), (2,'Bye') ) t;
$$ language SQL immutable;

CREATE FUNCTION foo_tab() RETURNS TABLE (score int, term text) AS $$
   SELECT * FROM ( VALUES (1,'hello!'), (2,'Bye') ) t;
$$ language SQL immutable;

SELECT * FROM foo();      -- works fine!
SELECT * FROM foo_tab();  -- works fine and is equivalent.
Run Code Online (Sandbox Code Playgroud)

所述SETOF RETURNS具有重用型的优点(参见footype),这是不可能用RETURNS TABLE.

  • `returns setof footype` 与 `RETURNS SETOF record` 不同,因为现在它不再是“未知”类型。`footype` 的列定义良好。 (2认同)