加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – postgres.超出了plpgsql堆栈深度限制

发布时间:2020-12-13 15:56:15 所属栏目:百科 来源:网络整理
导读:我正在处理一个简单的函数,它自动从表中更新某些东西. create or replace function total() returns void as $$declare sum int;begin sum = (SELECT count(copy_id) FROM copies); update totalbooks set all_books = sum where num = 1; end;$$language pl
我正在处理一个简单的函数,它自动从表中更新某些东西.

create or replace function total() 
returns void as $$
declare
  sum int;
begin
  sum = (SELECT count(copy_id) FROM copies);
    update totalbooks
    set all_books = sum
    where num = 1;
  end;
$$language plpgsql;

如果我执行“select total();”它工作得很好所以我做了一个函数触发器,以便它自动更新:

create or replace function total1() returns trigger as $$
begin
   perform (select total());
    return null;
end;
$$language plpgsql;

但在我执行之后:

create trigger total2
after update
on totalbooks
for each row
execute procedure total1();

它给了我一个错误信息:

ERROR:  stack depth limit exceeded
HINT:  Increase the configuration parameter "max_stack_depth" (currently 3072kB),after   ensuring the platform's stack depth limit is adequate.
CONTEXT:  SQL statement "SELECT (SELECT count(copy_id) FROM copies)"
PL/pgSQL function total() line 5 at assignment
SQL statement "SELECT (select total())"
PL/pgSQL function total1() line 3 at PERFORM
SQL statement "update totalbooks
set all_books = sum
where num = 1"
PL/pgSQL function total() line 6 at SQL statement
SQL statement "SELECT (select total())"
PL/pgSQL function total1() line 3 at PERFORM
SQL statement "update totalbooks
set all_books = sum
where num = 1"
PL/pgSQL function total() line 6 at SQL statement
SQL statement "SELECT (select total())"
PL/pgSQL function total1() line 3 at PERFORM
SQL statement "update totalbooks
set all_books = sum
where num = 1"
PL/pgSQL function total() line 6 at SQL statement
SQL statement "SELECT (select total())"
PL/pgSQL function total1() line 3 at PERFORM
SQL statement "update totalbooks
set all_books = sum
where num = 1"
PL/pgSQL function total() line 6 at SQL statement
SQL statement "SELECT (select total())"
PL/pgSQL function total1() line 3 at PERFORM
SQL statement "update totalbooks
set all_books = sum
where num = 1"
PL/pgSQL function total() line 6 at SQL statement
SQL statement "SELECT (select total())"
PL/pgSQL function total1() line 3 at PERFORM
SQL statement "update totalbooks
set all_books = sum
where num = 1"
PL/pgSQL function total() line 6 at SQL statement
SQL statement "SELECT (select total())"

显然我的触发器有问题.请帮忙.

我正在使用Postgres 9.2.4,由Visual C build 1600,64-Bit编译

编辑:

我试过pg_trigger_depth(),但现在触发器不会自动更新?我还是要执行’select total()’

这是我的新代码:

create or replace function total() 
returns void as $$
declare
  sum int;
begin
   sum = (SELECT count(copy_id) FROM copies);
    update totalbooks
    set all_books = sum;
end;
$$language plpgsql;


create or replace function total1() returns trigger as $$
begin
  perform (select total());
  return null;
end;
$$language plpgsql;

create trigger total2
after update
on totalbooks
for each row
WHEN (pg_trigger_depth()=0)
execute procedure total1();

解决方法

好的,如果您真的想要更新触发器,那么您可以做什么将此触发器设置为特定于列,以便在对all_books的更新时不会触发它,这会导致您的递归.像这样的东西 –

create trigger total2
after update of copy_id
on totalbooks
for each row
execute procedure total1();

当然,您可以更改哪些列触发该功能,我只选择了copy_id,因为这就是您所计算的.

然而

如果使用count()结果进行更新,则可以将触发器置于INSERT和DELETE操作上.这样,当计数改变时触发器将触发,但更新不会触发它. //编辑:由于您的总和只是副??本中所有记录的计数,因此只有在插入或更新记录时才会更改,因此无论如何在更新时运行此触发器都没有意义.

编辑:我认为添加到CREATE TRIGGER Documentation的链接会很有用.请参阅标记为“事件”的部分,因为这详细说明了如何在事件中指定列.

编辑新信息:

鉴于你需要完成的事情,我认为你需要重新思考你的数据设计,我建议你使用父子关系(任何时候你在表中的许多行缓存共享数据,因为它们共享一些共同点,表示您可能需要父表格).

有一个书籍表,其中每一行是关于一本书(标题,作者等)的信息,然后有一个副本表,其中每行包含有关书籍的一个副本(序列号,最后签出等)的信息.

这样,获取副本的数量就像SELECT COUNT(*)FROM副本WHERE book_id = [some book id]一样简单.

如果你真的想在某处缓存计数,可以在books表上进行.

在执行UPDATE书籍的副本上创建INSERT OR UPDATE触发器SET copy_count =(SELECT COUNT(*)FROM copies WHERE book_id = NEW.book_id)WHERE id = NEW.book_id.

然后在执行UPDATE书籍的副本上创建DELETE触发器SET copy_count =(SELECT COUNT(*)FROM copies WHERE book_id = OLD.book_id)WHERE id = OLD.book_id

两个触发器的原因是NEW变量仅在INSERT或UPDATE触发器中可用,而OLD仅在DELETE触发器中可用.你可以把它作为一个触发器来完成,但这需要的代码比我想要的更多.

确保所有触发器都是AFTER触发器,否则计数中不会考虑新插入/删除的行.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读