升级到 PostgreSQL 11:CASE 中不允许设置返回函数
Upgrading to PostgreSQL 11: set-returning functions are not allowed in CASE
从 PostgreSQL 9.6 升级到 11 时,以下查询停止工作:
with doc as (select * from documents where name = doc_id)
select jsonb_array_elements_text(permissions)
from users
where users.name = user_name
union
select
case
when doc.reader = user_name then 'read'
when doc.owner = user_name then unnest(array['read','write'])
else unnest(array[]::text[])
end
from doc;
union
像往常一样将两个值列表放在一起,两个列表可以有零个、一个或多个元素。
第一个 select
可以 return 零、一个或多个,因为那是 users
table.
中的内容
第二个 select
始终从 documents
table 扫描一行,但 return 为零、一行或多行,具体取决于 [=17= 】 决定。
PostgreSQL 9.6 按预期工作,PostgreSQL 11 说:
ERROR: set-returning functions are not allowed in CASE
LINE 56: else unnest(array[]::text[])
^
HINT: You might be able to move the set-returning function into a LATERAL FROM item.
感谢您的建议,但我不知道如何在这里使用 LATERAL FROM
。
这里的提示有点误导。正如它所说,向您的 set-returning 函数添加横向连接 可能 有帮助(一般而言),但我认为这对您的情况没有多大意义。
您可以轻松解决此问题,方法是将 CASE
表达式更改为 return 数组,然后取消嵌套结果:
...
select
unnest(
case
when doc.reader = user_name then array['read']
when doc.owner = user_name then array['read','write']
else array[]::text[]
end
)
from doc;
从 PostgreSQL 9.6 升级到 11 时,以下查询停止工作:
with doc as (select * from documents where name = doc_id)
select jsonb_array_elements_text(permissions)
from users
where users.name = user_name
union
select
case
when doc.reader = user_name then 'read'
when doc.owner = user_name then unnest(array['read','write'])
else unnest(array[]::text[])
end
from doc;
union
像往常一样将两个值列表放在一起,两个列表可以有零个、一个或多个元素。
第一个 select
可以 return 零、一个或多个,因为那是 users
table.
第二个 select
始终从 documents
table 扫描一行,但 return 为零、一行或多行,具体取决于 [=17= 】 决定。
PostgreSQL 9.6 按预期工作,PostgreSQL 11 说:
ERROR: set-returning functions are not allowed in CASE
LINE 56: else unnest(array[]::text[])
^
HINT: You might be able to move the set-returning function into a LATERAL FROM item.
感谢您的建议,但我不知道如何在这里使用 LATERAL FROM
。
这里的提示有点误导。正如它所说,向您的 set-returning 函数添加横向连接 可能 有帮助(一般而言),但我认为这对您的情况没有多大意义。
您可以轻松解决此问题,方法是将 CASE
表达式更改为 return 数组,然后取消嵌套结果:
...
select
unnest(
case
when doc.reader = user_name then array['read']
when doc.owner = user_name then array['read','write']
else array[]::text[]
end
)
from doc;