在不能接受集合的上下文中调用的集合值函数

Nul*_*lik 5 postgresql plpgsql set-returning-functions

我收到错误:

在不能接受集合的上下文中调用的集合值函数

RETURN QUERY EXECUTE在行执行此函数时:

PLSQL $ cat lookup_email.pl 
CREATE OR REPLACE FUNCTION app.lookup_email(ident_id bigint,sess bigint,company_id bigint,email varchar)
RETURNS SETOF RECORD as $$
DECLARE
    rec RECORD;
    comp_id bigint;
    server_session bigint;
    schema_name varchar;
    query varchar;
BEGIN
    schema_name:='comp' || company_id;
    select app.session.session into server_session from app.session where app.session.identity_id=ident_id and app.session.session=sess;
    IF FOUND
    THEN
        BEGIN
            query:='SELECT i.email,u.user_id FROM app.identity as i,' || schema_name || '.uzer as u WHERE i.email like ''%' || email || '%'' and i.identity_id=u.identity_id';
            RAISE NOTICE 'executing: %',query;
            RETURN QUERY EXECUTE query;
            RETURN;
        EXCEPTION
            WHEN OTHERS THEN
                RAISE NOTICE ' query error (%)',SQLERRM;

        END;
    END IF;
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

这是 psql 的输出:

dev=> select app.lookup_email(4,730035455897450,6,'u');
NOTICE:  executing: SELECT i.email,u.user_id FROM app.identity as i,comp6.uzer as u WHERE i.email like '%u%' and i.identity_id=u.identity_id
NOTICE:   query error (set-valued function called in context that cannot accept a set)
 lookup_email 
--------------
(0 rows)
Run Code Online (Sandbox Code Playgroud)

我知道查询不包含任何错误,因为它在另一个 psql 会话中工作:

dev=> SELECT i.email,u.user_id FROM app.identity as i,comp6.uzer as u WHERE i.email like '%u%' and i.identity_id=u.identity_id;
     email      | user_id 
----------------+---------
 hola@mundo.com |       1
(1 row)
Run Code Online (Sandbox Code Playgroud)

那么为什么 Postgres 会抱怨如果我将我的函数声明为 asRETURNS SETOF RECORD呢?我的错误在哪里?

Eva*_*oll 7

那么,如果我声明我的函数是一组记录,为什么 Postgres 会抱怨???我的错误在哪里?

  1. 在 FROM 子句中调用您的 Set Returning 函数。
  2. 始终指定您的类型。

它称为Set Returning Function,但您想要指定复合类型

这是完全有效的,

RETURNS SETOF RECORD $$
Run Code Online (Sandbox Code Playgroud)

但是,您可能必须使用以下方式调用它:

SELECT email, user_id
FROM 
    app.lookup_email(4,730035455897450,6,'u')
    AS t(email text, user_id integer)
Run Code Online (Sandbox Code Playgroud)

您无法在其中调用非类型化 SRF 的上下文是没有表定义的上下文。这种语法可能会变得令人讨厌,所以更容易更改RETURNS SETOF RECORD

RETURNS TABLE(email text, user_id integer) AS $$
Run Code Online (Sandbox Code Playgroud)

并在没有列定义列表的情况下使用该函数

SELECT email, user_id
FROM app.lookup_email(4,730035455897450,6,'u')
Run Code Online (Sandbox Code Playgroud)

在文档中查找更多信息