1

我有一个自定义类型:

create type some_type as (
    some_bool_param     boolean, 
    str                 varchar
);

我用这种类型的字段创建一个表并插入一些数据:

create table test_table (
    strs some_type
);

insert into test_table(strs) values
  ((false, 'First str'))
, ((false, 'Second str '))
, ((false, 'Third str'))
, ((false, 'Yet another str'));

现在我尝试返回 setofsome_type数据:

create or replace function get_str() returns setof some_type as
$$
declare
    r some_type;
begin
    for r in 
        select * from test_table loop
    return next r;
    end loop;
    return;
end;

我打电话get_str()

select * from get_str();

但是得到一个错误:

ERROR:  error in boolean type value: "(f,"First str")"
CONTEXT:  PL/pgSQL function "get_str" line 4 at FOR by result of SELECT

我该如何解决?

4

3 回答 3

5
create or replace function get_str() returns setof some_type as
$$
declare
    r some_type;
begin
    for r in 
        select strs from test_table loop
    return next r;
    end loop;
    return;
end;

以防万一:声明一个表也声明了它的行类型,所以这里不需要单独CREATE TYPE的。这也可以:

create table test_table (
    some_bool_param     boolean, 
    str                 varchar
);

insert into test_table values (false, 'First str');
insert into test_table values (false, 'Second str ');
insert into test_table values (false, 'Third str');
insert into test_table values (false, 'Yet another str');

create or replace function get_str()
returns setof test_table as
$$
    SELECT  *
    FROM    test_table;
$$
LANGUAGE sql;
于 2012-06-04T08:13:45.780 回答
4

对于这种功能,您不再需要使用当前版本的 PostgreSQL 循环。改用RETURN QUERY

CREATE OR REPLACE FUNCTION get_str()
  RETURNS SETOF test_table AS
$func$
BEGIN
   RETURN QUERY
   TABLE test_table;  -- shorthand for: SELECT * FROM test_table
END
$func$  LANGUAGE plpgsql;

或提供的@Quassnoi 之类的 SQL 函数。请注意,这将返回一个嵌套的复合类型 ( SETOF test_table, not SETOF some_type)。

奇怪的是,这也有效:

CREATE OR REPLACE FUNCTION get_str5()
  RETURNS SETOF some_type AS
$func$
   TABLE test_table;
$func$ LANGUAGE sql;

外部行包装器被默默地删除,这至少可以说是 Postgres 的一个古怪之处。

关于错误

您的功能将像这样工作:

CREATE OR REPLACE FUNCTION get_str()
  RETURNS TABLE (strs some_type) AS
$func$
BEGIN
   FOR strs IN
       SELECT (t.strs).* FROM test_table t
   LOOP
      RETURN NEXT r;
   END LOOP;
END
$func$ LANGUAGE plpgsql;

注意粗体部分。FOR对循环中的行或记录类型的分配是逐个子字段完成的。这通常很方便,但在使用嵌套复合类型时会让人感到困惑。

some_type您在表格行 ( ) 中有一个复合类型 ( test_table) -两级嵌套。这通常不是人们想要的,但这就是您向我们展示的。

您需要分解/解包两次

  • 您的原始代码仅使用select * from test_table.

  • @Quassnoi 的建议修复select strs from test_table以同样的方式失败: strs 通过直接引用从表行分解,但strs仍然是需要在分配之前自行分解的行类型。

于 2012-06-04T11:25:28.960 回答
2

根据其声明,函数 get_str() 应该返回一组具有结构的记录,该some_type结构是 2 列,1 个布尔值和 1 个 varchar。

该函数实际上返回一组记录,其中包含 1 列类型some_type

尝试替换return next r;return next r.strs;

于 2012-06-04T08:03:46.533 回答