2

我有一个递归的mysql存储过程,它总是返回最大499行。我的存储过程在树(不是二叉树)中移动,并检查节点是否有子节点等等,直到它到达叶子。

我不知道如何将我的代码转换为非递归方式,我只想问两个点:

  • 如何在 mysql 中进行无限递归(mysql 服务器版本为 5.5)?
  • 如果这不能发生,我怎样才能将我的 cod 更改为非递归方式?

    CREATE PROCEDURE `get_citations`(in _pub_id int(10),in _lvl int,citation_count int)
    BEGIN
    DECLARE done INT DEFAULT FALSE;
    declare p_id,c_count int;
    declare _counter int default 1;
    DECLARE cur1 CURSOR FOR SELECT pat_publn_id,cited_count from temp.a_citations 
    where pub_parent=_pub_id ;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    
    insert into a_citations
    (pat_publn_id ,
        publn_nr ,
        publn_kind,
        publn_auth,
        publn_date,
        cited_pat_publn_id,
        cited_count,
        pub_lvl,
        pub_parent)
            (select p.pat_publn_id,p.publn_nr,p.publn_kind,p.publn_auth,p.publn_date,c.cited_pat_publn_id,
            (select count(*) as cnt FROM patstat1304.tls212_citation c2 where c2.cited_pat_publn_id=c.pat_publn_id) as cited_count,_lvl as pub_lvl,_pub_id as pub_parent
            from patstat1304.tls212_citation c,patstat1304.tls211_pat_publn p
            where c.pat_publn_id=p.pat_publn_id and c.cited_pat_publn_id=_pub_id);
    commit;
    
    OPEN cur1;
    read_loop: LOOP
    
     fetch cur1 into p_id,c_count;
    IF (c_count !=0) then       
            call get_citations( p_id,_lvl+1,c_count);
            commit;
    
    END if;
    IF done THEN
          LEAVE read_loop;
        END IF;
    set _counter=_counter+1;
    
    if(_counter=citation_count) then
     LEAVE read_loop;
    end if;
    end loop;
    CLOSE cur1;
    
    END
    
4

1 回答 1

0

MySQL can not execute stored procedures with a very deep nesting.

Very soon, error ER_STACK_OVERRUN_NEED_MORE will appear.

Increasing the thread stack to go further will not work either.

To change the recursive call to a non recursive one, consider something like this:

1) Create a table named publications_to_process, with the publication and search level.

2) To start the search, insert the original publication in this table, with level 1.

3) In a loop, fetch one publication, examine the citations, and add the publications listed in the publications_to_process, incrementing the level.

4) As a bonus, for cases like:

Pub_1 --> Pub_2 --> Pub_3, Pub_1 --> Pub_3

there is no need to add Pub_3 again to the search if it has been processed already.

In other words, the publications are more likely to be a directed graph that a tree.

5) Either make the table temporary, or consider adding a PROCESSLIST_ID column, so that different sessions (having a different CONNECTION_ID()) do not step on each other, when executing this search in parallel.

于 2013-09-27T16:07:50.200 回答