当返回类型是表名时,为啥 PostgreSQL 函数返回空列而不是没有行?

Posted

技术标签:

【中文标题】当返回类型是表名时,为啥 PostgreSQL 函数返回空列而不是没有行?【英文标题】:Why do PostgreSQL functions return null columns instead of no rows when the return type is a table name?当返回类型是表名时,为什么 PostgreSQL 函数返回空列而不是没有行? 【发布时间】:2020-02-14 08:04:30 【问题描述】:

如果我创建一个函数f 来查询一个函数,我认为如果返回类型是表的名称而不是RETURNS TABLE(id integer, name text),那么它会更容易阅读。

CREATE TABLE users ( id integer, name text );

CREATE OR REPLACE FUNCTION f() 
 RETURNS users 
 AS $$ 
   SELECT * FROM users
   WHERE FALSE 
 $$ 
 LANGUAGE SQL;

但是当函数中的查询返回零行时,我得到了奇怪的结果。

SELECT * FROM f();

预期结果

+------+--------+
| id   | name   |
|------+--------|
+------+--------+

实际结果

+--------+--------+
| id     | name   |
|--------+--------|
| <null> | <null> |
+--------+--------+

如果有更多列,它们仍然都是null。如果函数中的查询返回任何行,则它按预期工作。如果我使用 RETURNS TABLE(...) 语法,我不会出现这种行为。

有没有办法解决这个问题?

我使用的是 PostgreSQL 9.6

【问题讨论】:

【参考方案1】:

这与返回类型无关,但与您将函数声明为返回单行这一事实有关。

替换

RETURNS users

RETURNS SETOF users

您的功能将按预期工作。

与您的函数一样,如果查询没有结果,它将返回 NULL,如果查询有多个结果行,它将返回第一行。

【讨论】:

以上是关于当返回类型是表名时,为啥 PostgreSQL 函数返回空列而不是没有行?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Identity - 将用户 ID 主键默认类型从字符串更改为 int 以及使用自定义表名时出错

hibernate映射postgreSQL数据库中的表时,表名是大写的时候为啥hibernate不能映射实体

为啥 PostgreSQL 不喜欢大写的表名?

openpyxl传入表名时不要使用默认的sheet表名

语句有动态表名时如何防止SQL注入?

语句有动态表名时如何防止SQL注入?