获得“无法开放的关系”简单查询的错误
我的函数可以将一组插入到...值脚本中。如果我取消dvp.content行,则该函数会以“错误:无法与oid ###”打开关系,该功能是指临时表。 content
列是JSONB类型。不确定从哪里开始?
CREATE OR REPLACE FUNCTION export_docs_as_sql(doc_list uuid[], to_org_id uuid)
RETURNS table(id integer, sql text)
AS $$
BEGIN
...
-- use a temp table to gather all INSERT statements
CREATE TEMP TABLE IF NOT EXISTS doc_data_export(
id serial PRIMARY KEY,
sql text
);
...
-- get doc_version_pages
INSERT INTO doc_data_export(sql)
SELECT 'INSERT INTO doc_version_pages(id, doc_version_id, persona_id, care_category_id, patient_group_id, title, content, created_at, updated_at, is_guide, is_root) VALUES (' ||
quote_literal(dvp.id::TEXT) || ', ' ||
quote_literal(dvp.doc_version_id::TEXT) || ', ' ||
CASE WHEN p.name IS NOT NULL THEN '(SELECT px.id FROM personas px WHERE px.org_id = ' || quote_literal(dv.id::TEXT) || ' AND px.name = ' || quote_literal(p.name) || '), ' ELSE 'NULL, ' END ||
CASE WHEN c.name IS NOT NULL THEN '(SELECT cx.id FROM care_categories cx WHERE cx.org_id = ' || quote_literal(to_org_id) || ' AND cx.name = ' || quote_literal(c.name) || '), ' ELSE 'NULL, ' END ||
CASE WHEN g.name IS NOT NULL THEN '(SELECT gx.id FROM patient_groups gx WHERE gx.org_id = ' || quote_literal(to_org_id) || ' AND gx.name = ' || quote_literal(g.name) || '), ' ELSE 'NULL, ' END ||
quote_literal(dvp.title::TEXT) || ', ' ||
--dvp.content || ', ' ||
quote_literal(dvp.created_at::TEXT) || ', ' ||
quote_literal(now()::timestamp) || ', ' ||
quote_literal(dvp.is_guide::TEXT) || ', ' ||
quote_literal(dvp.is_root::TEXT) || ');'
FROM unnest(doc_list) l
INNER JOIN doc_versions dv ON l = dv.doc_id
INNER JOIN doc_version_pages dvp ON dv.id = dvp.doc_version_id
LEFT JOIN personas p ON dvp.persona_id = p.id
LEFT JOIN care_categories c ON dvp.care_category_id = c.id
LEFT JOIN patient_groups g ON dvp.patient_group_id = g.id;
...
-- output all inserts
RETURN QUERY SELECT * FROM doc_data_export;
-- drop temp table
DROP TABLE doc_data_export;
END;
$$ LANGUAGE plpgsql;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于描述的错误这里,这仍然是Postgres 14.0的问题:
为了进一步解释,当列值大于
toast_tuple_threshold
配置参数(通常是2KB)时,无法压缩或使用列配置外部
,的存储参数时该值将分解成块,并存储在一个称为吐司表的特殊辅助表中。该表将存储在pg_toast
架构中,并将命名为pg_toast.pg_toast_< table oid>
。因此,当您将
dvp.content
添加到SQL语句中时,您将其插入doc_data_export
中时,其中一些值大于上述约束,因此被敬酒。您的返回查询
仅将指针发送到吐司表中的值。返回完成后,临时表及其相应的吐司表被删除。因此,当外部查询试图实现结果时,它找不到这些指针参考的吐司表 - 因此,您看到的隐秘错误消息。您可以避免为临时表发送吐司指针 - 因此,在
返回查询
- 通过在sql
列上执行一个返回相同值的操作后,将其放置在下面的简单功能将在将
设置为
true 时,将重现吐司错误的最小示例代码> false 。The "Could Not Open Relation" problem is occurring due to the bug described here, which remains an issue as of Postgres 14.0:
To explain further, when a column value is greater than the
TOAST_TUPLE_THRESHOLD
configuration parameter (usually 2KB) and cannot be compressed or when the column is configured with a storage parameter ofEXTERNAL
, the value will be broken down into chunks and stored in a special secondary table called a TOAST table. This table will be stored in thepg_toast
schema and will be named likepg_toast.pg_toast_<table OID>
.So when you add
dvp.content
to the sql statement you insert that intodoc_data_export
, some of these values are larger than the aforementioned constraints and are thus TOASTed. YourRETURN QUERY
is only sending the pointers to the values in the toast table. After the return is done, the temporary table and its corresponding TOAST table is dropped. Thus when the outer query attempts to materialize the results, it can't find the TOAST table that these pointers reference - hence the cryptic error message you see.You can avoid sending TOAST pointers for the temporary table -and thus safely DROP it after the
RETURN QUERY
-by performing an operation on thesql
column that returns the same value:The simple function below will reproduce a minimal example of the TOAST bug when you set
fail
totrue
and demonstrate the successful workaround when you setfail
tofalse
.