而不是使用 Oracle 序列触发

Instead of trigger with Oracle sequence

我有一些旧应用程序(遗留应用程序)使用它们自己的 MAX NUMBER table。问题是我们不能同时修改和发布所有的应用程序。因此,我们希望分阶段进行。

我提出了以下建议。但是,我不知道为什么Oracle在我执行更新语句时执行视图的select查询。

当前使用情况:

-- Update the max number table
Update Sysadm.DummyTable
Set MaxNumber = MaxNumber + 1;

-- An application needs to select current value from the MaxNumber table.
Select * From Sysadm.DummyTable;

建议的解决方案:

CREATE SEQUENCE SYSADM.SEQ_DummyTable START WITH 12345 INCREMENT BY 1;

--- Common function ---
--- The following function will get the current sequence number of the Oracle sequence across all the sessions.
CREATE OR REPLACE FUNCTION Sysadm.GetCurrValue(sLSeqName VARCHAR)
    RETURN NUMBER
AS nLDummy NUMBER;
BEGIN
    if (sLSeqName = 'SEQ_DUMMYTABLE') Then
        SELECT SEQ_DUMMYTABLE.CURRVAL Into nLDummy FROM DUAL;
    Else
        Return null;
    End If;

    RETURN(nLDummy);
END;
/

--- The existing DummyTable table will be dropped and DummyTable (exactly with the same name including its structure) view will be created.
Create or Replace View Sysadm.DummyTable (MAXNUMBER)
As
Select sysadm.GetCurrValue('SEQ_DUMMYTABLE') As MAXNUMBER From Sysadm.ABC Where RowNum = 1;

--- The following trigger will get executed when the application tried to update the DummyTable table. This trigger will get executed instead of update statement from the application.
Create Or Replace Trigger Sysadm.TR_DummyTable
Instead of UPDATE ON Sysadm.DummyTable
Declare
    nLDummy NUMBER;
Begin
    SELECT SEQ_DUMMYTABLE.NEXTVAL Into nLDummy FROM DUAL;
End;
/

我在视图上使用 而不是 触发器。但是,当我尝试执行以下更新查询时,我收到一条错误消息。

-- Update the max number table
Update Sysadm.DummyTable
Set MaxNumber = MaxNumber + 1;

ORA错误信息:

    Error starting at line : 1 in command -
    Update Sysadm.DUMMYTABLE Set MaxNumber = MaxNumber + 1
    Error report -
    SQL Error: ORA-08002: sequence SEQ_DUMMYTABLE.CURRVAL is not yet defined in this session
    ORA-06512: at "SYSADM.GETCURRVALUE", line 10
    08002. 00000 -  "sequence %s.CURRVAL is not yet defined in this session"
    *Cause:    sequence CURRVAL has been selected before sequence NEXTVAL
    *Action:   select NEXTVAL from the sequence before selecting CURRVAL

正如 Oracle 告诉您的那样:如果您没有从该会话中的序列中获取,则无法获取 currval,您可以通过选择 nextval 来获取。例如:

SQL> create sequence seqa;

Sequence created.

这不起作用 - 你已经知道了,你已经遇到了错误:

SQL> select seqa.currval from dual;
select seqa.currval from dual
       *
ERROR at line 1:
ORA-08002: sequence SEQA.CURRVAL is not yet defined in this session

因此:nextval 首先,currval 其次(如果需要的话):

SQL> select seqa.nextval from dual;

   NEXTVAL
----------
         1

SQL> select seqa.currval from dual;

   CURRVAL
----------
         1

SQL>

在你的情况下,这意味着这看起来像

if (sLSeqName = 'SEQ_DUMMYTABLE') Then
    SELECT SEQ_DUMMYTABLE.NEXTVAL Into nLDummy FROM DUAL;
Else                      -------

只需更改功能,我们就可以让它工作。这也将解决并发问题:

--- The following function will get the current sequence number of the Oracle sequence across all the sessions.
CREATE OR REPLACE FUNCTION Sysadm.GetCurrValue(sLSeqName VARCHAR)
    RETURN NUMBER
AS nLDummy NUMBER;
BEGIN
    if (sLSeqName = 'SEQ_DUMMYTABLE') Then
        SELECT SEQ_DUMMYTABLE.CURRVAL Into nLDummy FROM DUAL;
    Else
        Return null;
    End If;

    RETURN(nLDummy);
EXCEPTION
    WHEN OTHERS THEN
        RETURN NULL;
END;
/