如何将 RETURNS TABLE 与 PostgreSQL 中的现有表一起使用?

tin*_*lyx 8 postgresql set-returning-functions postgresql-9.5

来自此处的 PostgreSQL文档

还有另一种方法可以将函数声明为返回一个集合,即使用语法 RETURNS TABLE(columns)。... 这种表示法是在 SQL 标准的最新版本中指定的,因此可能比使用 SETOF 更具可移植性。

这听起来好像RETURNS TABLE是返回多行的更新、更便携的样式。但我不确定这两种语法是否等效。

我想知道我们是否真的可以RETURNS TABLE用来代替 RETURNS SETOF

特别是,我还没有弄清楚的一种情况是:如果我们有一个现有的表foo及其关联的复合类型,我们如何在 中使用它RETURNS TABLE

使用上述链接的示例,可以使用以下内容重写RETURNS TABLE

CREATE TABLE foo (fooid int, foosubid int, fooname text);
CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$
    SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)

到目前为止,我尝试使用RETURNS TABLE (foo.*)and RETURNS TABLE (foo),但没有用。

Pet*_*uss 5

PS:抱歉我的评论,我正在开发一个复杂的代码,我有一个小错误,似乎是PostgreSQL对“返回表”部分的愚蠢限制......我很愚蠢,而不是集中精力解决它,我使用了互联网(搜索引擎把我放在这里)。现在,这个wiki-answer是为了帮助其他被搜索引擎调用并被问题标题所吸引的读者。

感谢@dezso(是一个正确的答案),请所有读者,您可以编辑此问题以使其更具教学性,它是一个 Wiki。


从 PostgreSQL-v8 我们可以做到!我们可以返回 EXISTING_TABLE_NAME

在其指南中,在所有 PostgreSQL 版本中,从pg v8当前版本,都有一个名为 “SQL 函数作为表源”的部分。让我们通过一些简化重现指南的示例:

CREATE TABLE foo (fooid int, foosubid int, fooname text);
INSERT INTO foo VALUES (1, 1, 'Joe'), (1, 2, 'Ed'), (2, 1, 'Mary');

CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$
    SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;

SELECT * FROM getfoo(1);
Run Code Online (Sandbox Code Playgroud)

它按预期运行,非常完美!

 fooid | foosubid | fooname
-------+----------+---------
     1 |        1 | Joe
     1 |        2 | Ed
Run Code Online (Sandbox Code Playgroud)

问题“如何将 RETURNS TABLE 与 PostgreSQL 中的现有表一起使用?” 自 pg v8 以来有一个很好的答案......这是我们在过去 15 年中的做法
  RETURNS SETOF <EXISTING_TABLE_NAME>
语法是: .

使用子句 TABLE 作为即时 CREATE TABLE 返回

@tinlyx 的混淆,在他的问题中解释,是关于使用子句TABLE而不是SETOF......要考虑使用“PostgreSQL 语法逻辑”,我们必须首先记住这RETURN <EXISTING_TABLE_NAME>也是有效的,并且它具有相同的行为RETURN <EXISTING_TYPE_NAME>。很自然的只返回一行。

下一步,请记住我们使用 CREATE TABLE 子句 (<tuple_description>) 声明了一个元组,因此,表达“即时定义元组表”的好语法是 RETURN TABLE (<tuple_description>),并且return TABLE 类型,类似于数组类型,将返回多个实例(TABLE 是一组元组)。

下一步,请记住我们用子句声明了一个元组CREATE TABLE (<tuple_description>),因此,表达“即时表定义”的好语法是RETURN TABLE (<tuple_description>);并且返回 Table-type 是有意义的,就像 Array-type 一样,它们返回多个实例(TABLE 是一组元组)。

PostgreSQL (!) 中的“现代事物”就是@ZiggyCrueltyfreeZeitgeister 所展示的RETURNS TABLE (LIKE <table_name>)语法。

CREATE FUNCTION getfoo2(int) RETURNS TABLE (LIKE foo) AS $$ -- working fine!
    SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;
SELECT * FROM getfoo2(1); -- same result as getfoo(1)
Run Code Online (Sandbox Code Playgroud)

方法很多,总结一下:

显式表名(两种方式)或类型名:

  • RETURNS TABLE (LIKE <table_name>) (现代和好)
  • RETURNS SETOF <table_name> (老但是好)
  • RETURNS SETOF <type_name>(之后 CREATE TYPE <type_name> (<tuple_description>)

隐式/通用方式,匿名类型:

  • RETURNS SETOF RECORD (通用但有时有问题)
  • (存在的东西?) RETURNS SETOF ROW?

瞬时表定义:

  • RETURNS TABLE (<tuple_description>)
  • (no RETURNS)OUT在参数列表中使用。

对于最后一种情况,用我们的例子来说明:
CREATE FUNCTION getfoo(int, OUT fooid int, OUT foosubid int, OUT fooname text)

对于动态和/或多态输入,您必须查看此说明

最佳实践?

有很多方法可以做同样的事情,那么,有一个“最好的”吗?

作为语法,我更喜欢使用RETURNS TABLE (LIKE <table_name>),这是明确的:不要与“隐式记录”混淆,不用担心不兼容......

对于库管理很重要,DROP TABLE foo CASCADE也会删除功能:在任何语法(returns tablereturns setof)中,PostgreSQL 都会做得很好。

drop table foo cascade;
NOTICE:  drop cascades to 2 other objects
DETAIL:  drop cascades to function getfoo(integer)
drop cascades to function getfoo2(integer)
Run Code Online (Sandbox Code Playgroud)