暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 从表中获取顺序编号并锁定

askTom 2021-09-06
268

问题描述

亲爱的汤姆,
我们有一个表格,其中包含不同发票类型的记录。一列包含最后一张发票的编号。
我们需要一个函数来锁定记录计数为1 ,然后存储新的数字,确保没有其他会话得到相同的数字。

我们有这个密码
          lock table codif_vdok_nr in  row exclusive mode;    
          begin     
            select t.co_donr_nr+1,t.co_donr_jahr
              into p_doku_nr,p_jahr
              from codif_vdok_nr t
            where t.co_donr_vser_id = p_vser_id
              and t.co_donr_von <= trim(sysdate) -- 21.02.2009
              and nvl(t.co_donr_bis,sysdate) >= trim(sysdate) -- to_date(sysdate,'dd.mm.yyyy')
            for update nowait;
          exception 
            when others then
            po_message := 'doku_nr: Fehler Suche DokumentNr - Serie: ' || to_char(p_vser_id) || ' ' || sqlerrm; 
            raise_application_error(-20010,po_message ); 
          end;   

   update codif_vdok_nr t
      set t.co_donr_nr = p_doku_nr
      where t.co_donr_vser_id = p_vser_id
           and trunc(t.co_donr_von) <= trunc(sysdate)
              and trunc(nvl(t.co_donr_bis,sysdate)) >= trunc(sysdate);                            
复制


但碰巧两个疗程的发票号码是一样的。
你能告诉我错误在哪里或者如何解决吗?

致意
安德烈亚斯

专家解答

我不知道如何确切的更新关系到选择为更新以上。所以我不知道为什么你会得到重复的号码。

这就是说,该代码有几个潜在的问题,包括:

-修剪(sysdate) =>隐式到_char的转换。这可能会导致意想不到的结果:

select * from dual
where  sysdate = sysdate;

DUMMY   
X   

select * from dual
where  trim ( sysdate ) = sysdate;

no rows selected
复制


-使用sysdate作为筛选器意味着可以为给定的co_donr_vser_id选择不同的行。会是这个原因吗?

-如何阻止其他代码插入/更新此表?

- When other错误处理程序可能被任何东西触发(例如, too_many_rows )。如果for更新失败,更新是否仍执行?如果是,则值p_doku_nr来自何处?

我猜你是在用这个来生成无间隙的数字。

这是一个很难解决的问题。如上所述,即使代码工作正常,如何阻止有人直接在SQL*Plus/dev/cl中更改表?或者甚至是其他页面的应用?

你最好接受会有差距。使用序列生成数字并审计对表的所有更改:

https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:317107500346751182
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:1508205334476
文章转载自askTom,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论