Oracle无法执行dml操作,无法在查询中调用

Oracle无法执行dml操作,无法在查询中调用,oracle,plsql,Oracle,Plsql,我有这个函数cash_out_ticket,它通过游标,然后游标项通过IF语句运行。如果条件满足,它需要返回cash_out并运行程序end_of_ticket。 但当我从dual调用cash_out_ticket时,我得到一个错误,即我无法在查询中执行dml操作 在我的例子中,dml操作在票据的末尾。它不返回任何内容,只需从IN参数中执行一些更新 当if中的条件正确时,是否有方法调用票证的结束?正如错误所述,您不能从查询中调用函数,因为它调用的过程中有DML insert/update/del

我有这个函数cash_out_ticket,它通过游标,然后游标项通过IF语句运行。如果条件满足,它需要返回cash_out并运行程序end_of_ticket。 但当我从dual调用cash_out_ticket时,我得到一个错误,即我无法在查询中执行dml操作

在我的例子中,dml操作在票据的末尾。它不返回任何内容,只需从IN参数中执行一些更新


当if中的条件正确时,是否有方法调用票证的结束?

正如错误所述,您不能从查询中调用函数,因为它调用的过程中有DML insert/update/delete。所以你不能这样做:

CREATE OR REPLACE FUNCTION cash_out_ticket(party_id   IN softdev.casino_users.party_id%TYPE ,session_id IN softdev.bus_session.session_id%TYPE                       
    ) RETURN NUMBER AS ret_val NUMBER;  

    P_EXCHANGE_BET_CREDITS softdev.COUNTRY.EXCHANGE_BET_CREDITS%type;
    P_EXCHANGE_VALUE       softdev.COUNTRY.EXCHANGE_VALUE%type;
    p_reserved_funds       softdev.casino_users.credits%type;
    p_session_id           softdev.bus_session.session_id%type;
    p_session_close        softdev.bus_session.session_close%type;
    ticket_closed          exception;

    CURSOR cur_tkt_sess (party_id IN softdev.casino_users.party_id%TYPE,session_id IN softdev.bus_session.session_id%TYPE)        
       IS 
          SELECT bs.session_id  
                ,tii.status  
                ,ROW_NUMBER() OVER (PARTITION BY bs.session_id ORDER BY status ASC)  rn  
                ,NVL(TO_CHAR(bs.started, 'DD.MM.YYYY HH24:MI'), 'Live')  started  
                ,bs.bet  bet  
              --  ,bs.player_win * P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE AS possible_win  
              --  ,bs.house_win                                           AS odds  
                ,tii.time_p  
                ,tii.live_prematch  
                ,cash_out(bet)  cash_out  
            FROM bus_session bs  
                ,ticket_items tii  
           WHERE bs.session_id              = tii.bus_session_session_id  
             AND bs.session_type            = 'TICKET SESSION'  
             AND bs.party_id                = cur_tkt_sess.party_id  
             AND bs.session_id              = cur_tkt_sess.session_id  
             AND NVL(bs.session_close, 'N') = 'N';               
       rec_tkt_sess cur_tkt_sess%ROWTYPE;  

    BEGIN          
        CHAGE_CREDITS (party_id, P_EXCHANGE_BET_CREDITS, P_EXCHANGE_VALUE);      
       OPEN cur_tkt_sess(cash_out_ticket.party_id, cash_out_ticket.session_id);  

       FETCH cur_tkt_sess  
        INTO rec_tkt_sess;  

       IF(cur_tkt_sess%FOUND) THEN  

        IF(  
             (TO_DATE(rec_tkt_sess.started,'DD.MM.YYYY HH24:MI:SS') +1 <=SYSDATE)  -- je li tiket stariji od 24h
             OR  
             (rec_tkt_sess.live_prematch != '0')  --je li live (1 live , 0 not live)
             OR  
             (rec_tkt_sess.time_p <SYSDATE)  -- je li utakmice počela
            ) 
            THEN  
                ret_val := 0; 
            ELSE  
             ret_val := rec_tkt_sess.cash_out* P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE;

             play_beting.end_of_ticket(cash_out_ticket.session_id ,rec_tkt_sess.cash_out* P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE ,cash_out_ticket.party_id );
             --this procedure do updates , does not return anything. And it need to be run when conditions are fulfilled.

            END IF;  

         ELSE     
          ret_val := -1;            

       END IF;  

       RETURN(ret_val); 
END cash_out_ticket;
您可以从PL/SQL上下文调用它,例如在匿名块中:

select cash_out_ticket(42, 123) from dual;

ORA-14551: cannot perform a DML operation inside a query 

根据您计划调用它的位置和方式,您可以使用绑定变量来检索返回值。

正如错误所述,您无法从查询中调用函数,因为它调用的过程中存在DML insert/update/delete。所以你不能这样做:

CREATE OR REPLACE FUNCTION cash_out_ticket(party_id   IN softdev.casino_users.party_id%TYPE ,session_id IN softdev.bus_session.session_id%TYPE                       
    ) RETURN NUMBER AS ret_val NUMBER;  

    P_EXCHANGE_BET_CREDITS softdev.COUNTRY.EXCHANGE_BET_CREDITS%type;
    P_EXCHANGE_VALUE       softdev.COUNTRY.EXCHANGE_VALUE%type;
    p_reserved_funds       softdev.casino_users.credits%type;
    p_session_id           softdev.bus_session.session_id%type;
    p_session_close        softdev.bus_session.session_close%type;
    ticket_closed          exception;

    CURSOR cur_tkt_sess (party_id IN softdev.casino_users.party_id%TYPE,session_id IN softdev.bus_session.session_id%TYPE)        
       IS 
          SELECT bs.session_id  
                ,tii.status  
                ,ROW_NUMBER() OVER (PARTITION BY bs.session_id ORDER BY status ASC)  rn  
                ,NVL(TO_CHAR(bs.started, 'DD.MM.YYYY HH24:MI'), 'Live')  started  
                ,bs.bet  bet  
              --  ,bs.player_win * P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE AS possible_win  
              --  ,bs.house_win                                           AS odds  
                ,tii.time_p  
                ,tii.live_prematch  
                ,cash_out(bet)  cash_out  
            FROM bus_session bs  
                ,ticket_items tii  
           WHERE bs.session_id              = tii.bus_session_session_id  
             AND bs.session_type            = 'TICKET SESSION'  
             AND bs.party_id                = cur_tkt_sess.party_id  
             AND bs.session_id              = cur_tkt_sess.session_id  
             AND NVL(bs.session_close, 'N') = 'N';               
       rec_tkt_sess cur_tkt_sess%ROWTYPE;  

    BEGIN          
        CHAGE_CREDITS (party_id, P_EXCHANGE_BET_CREDITS, P_EXCHANGE_VALUE);      
       OPEN cur_tkt_sess(cash_out_ticket.party_id, cash_out_ticket.session_id);  

       FETCH cur_tkt_sess  
        INTO rec_tkt_sess;  

       IF(cur_tkt_sess%FOUND) THEN  

        IF(  
             (TO_DATE(rec_tkt_sess.started,'DD.MM.YYYY HH24:MI:SS') +1 <=SYSDATE)  -- je li tiket stariji od 24h
             OR  
             (rec_tkt_sess.live_prematch != '0')  --je li live (1 live , 0 not live)
             OR  
             (rec_tkt_sess.time_p <SYSDATE)  -- je li utakmice počela
            ) 
            THEN  
                ret_val := 0; 
            ELSE  
             ret_val := rec_tkt_sess.cash_out* P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE;

             play_beting.end_of_ticket(cash_out_ticket.session_id ,rec_tkt_sess.cash_out* P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE ,cash_out_ticket.party_id );
             --this procedure do updates , does not return anything. And it need to be run when conditions are fulfilled.

            END IF;  

         ELSE     
          ret_val := -1;            

       END IF;  

       RETURN(ret_val); 
END cash_out_ticket;
您可以从PL/SQL上下文调用它,例如在匿名块中:

select cash_out_ticket(42, 123) from dual;

ORA-14551: cannot perform a DML operation inside a query 
根据您计划调用它的位置和方式,您可以使用绑定变量来检索返回值