包含数据修改语句的WITH子句必须处于顶层SQL状态:0A000

Dan*_*pka 3 postgresql

我编写了函数,该函数使用WITH构造并将其插入表中,如下所示:

CREATE OR REPLACE FUNCTION test_func()
RETURNS json AS
$BODY$
begin
 return (
   with t as (
     insert into t(id) 
     select 1
     returning *
    )
 select '{"a":"a"}'::json
 );
end;
$BODY$
 LANGUAGE plpgsql VOLATILE;
select test_func()
Run Code Online (Sandbox Code Playgroud)

多数民众赞成返回错误:

ERROR: WITH clause containing a data-modifying statement must be at the top level
SQL-?????????: 0A000
Run Code Online (Sandbox Code Playgroud)

如果执行

   with t as (
     insert into t(id) 
     select 1
     returning *
    )
 select '{"a":"a"}'::json
Run Code Online (Sandbox Code Playgroud)

结果无错误。为什么会发生这种情况以及如何解决呢?

Łuk*_*ski 5

您正在对该查询执行子选择,这就是为什么它不起作用的原因。这也不起作用:

select * from (
   with t as (
     insert into t(id) 
     select 10
     returning *
    )
 select '{"a":"a"}'::json
) as sub
Run Code Online (Sandbox Code Playgroud)

有一些解决方案。

a)声明为退货setof并使用return query

CREATE OR REPLACE FUNCTION test_func()
RETURNS setof json AS
$BODY$
begin
return query
   with t as (
     insert into t(id) 
     select 7
     returning *
    )
 select '{"a":"a"}'::json;
end;
$BODY$
 LANGUAGE plpgsql VOLATILE;
Run Code Online (Sandbox Code Playgroud)

b)声明为 language sql

CREATE OR REPLACE FUNCTION test_func()
RETURNS json AS
$BODY$
   with t as (
     insert into t(id) 
     select 8
     returning *
    )
 select '{"a":"a"}'::json;
$BODY$
 LANGUAGE sql VOLATILE;
Run Code Online (Sandbox Code Playgroud)

c)在参数列表中声明输出变量并将结果分配给它们

CREATE OR REPLACE FUNCTION test_func(OUT my_out_var json)
AS
$BODY$
begin
   with t as (
     insert into t(id) 
     select 9
     returning *
    )
 select '{"a":"a"}'::json INTO my_out_var;
end;
$BODY$
 LANGUAGE plpgsql VOLATILE;
Run Code Online (Sandbox Code Playgroud)