Sleep function in ORACLE

后端 未结 11 1874
一整个雨季
一整个雨季 2020-11-30 00:52

I need execute an SQL query in ORACLE it takes a certain amount of time. So I wrote this function:

CREATE OR REPLACE FUNCTION MYSCHEMA.TEST_SLEEP
(
TIME_  I         


        
相关标签:
11条回答
  • 2020-11-30 01:00

    From Oracle 18c you could use DBMS_SESSION.SLEEP procedure:

    This procedure suspends the session for a specified period of time.

    DBMS_SESSION.SLEEP (seconds  IN NUMBER)
    

    DBMS_SESSION.sleep is available to all sessions with no additional grants needed. Please note that DBMS_LOCK.sleep is deprecated.

    If you need simple query sleep you could use WITH FUNCTION:

    WITH FUNCTION my_sleep(i NUMBER)
    RETURN NUMBER
    BEGIN
        DBMS_SESSION.sleep(i);
        RETURN i;
    END;
    SELECT my_sleep(3) FROM dual;
    
    0 讨论(0)
  • 2020-11-30 01:02

    What's about Java code wrapped by a procedure? Simple and works fine.

    CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED SNOOZE AS
    public final class Snooze {
      private Snooze() {
      }
      public static void snooze(Long milliseconds) throws InterruptedException {
          Thread.sleep(milliseconds);
      }
    }
    
    CREATE OR REPLACE PROCEDURE SNOOZE(p_Milliseconds IN NUMBER) AS
        LANGUAGE JAVA NAME 'Snooze.snooze(java.lang.Long)';
    
    0 讨论(0)
  • 2020-11-30 01:11

    It would be better to implement a synchronization mechanism. The easiest is to write a file after the first file is complete. So you have a sentinel file.

    So the external programs looks for the sentinel file to exist. When it does it knows that it can safely use the data in the real file.

    Another way to do this, which is similar to how some browsers do it when downloading files, is to have the file named base-name_part until the file is completely downloaded and then at the end rename the file to base-name. This way the external program can't "see" the file until it is complete. This way wouldn't require rewrite of the external program. Which might make it best for this situation.

    0 讨论(0)
  • 2020-11-30 01:17

    You can use DBMS_PIPE.SEND_MESSAGE with a message that is too large for the pipe, for example for a 5 second delay write XXX to a pipe that can only accept one byte using a 5 second timeout as below

    dbms_pipe.pack_message('XXX');<br>
    dummy:=dbms_pipe.send_message('TEST_PIPE', 5, 1);
    

    But then that requires a grant for DBMS_PIPE so perhaps no better.

    0 讨论(0)
  • 2020-11-30 01:20

    Short of granting access to DBMS_LOCK.sleep, this will work but it's a horrible hack:

    IN_TIME INT; --num seconds
    v_now DATE;
    
    -- 1) Get the date & time 
    SELECT SYSDATE 
      INTO v_now
      FROM DUAL;
    
    -- 2) Loop until the original timestamp plus the amount of seconds <= current date
    LOOP
      EXIT WHEN v_now + (IN_TIME * (1/86400)) <= SYSDATE;
    END LOOP;
    
    0 讨论(0)
  • 2020-11-30 01:20

    Create a procedure which just does your lock and install it into a different user, who is "trusted" with dbms_lock ( USERA ), grant USERA access to dbms_lock.

    Then just grant USERB access to this function. They then wont need to be able to access DBMS_LOCK

    ( make sure you don't have usera and userb in your system before running this )

    Connect as a user with grant privs for dbms_lock, and can create users

    drop user usera cascade;
    drop user userb cascade;
    create user usera default tablespace users identified by abc123;
    grant create session to usera;
    grant resource to usera;
    grant execute on dbms_lock to usera;
    
    create user userb default tablespace users identified by abc123;
    grant create session to userb;
    grant resource to useb
    
    connect usera/abc123;
    
    create or replace function usera.f_sleep( in_time number ) return number is
    begin
     dbms_lock.sleep(in_time);
     return 1;
    end;
    /
    
    grant execute on usera.f_sleep to userb;
    
    connect userb/abc123;
    
    /* About to sleep as userb */
    select usera.f_sleep(5) from dual;
    /* Finished sleeping as userb */
    
    /* Attempt to access dbms_lock as userb.. Should fail */
    
    begin
      dbms_lock.sleep(5);
    end;
    /
    
    /* Finished */
    
    0 讨论(0)
提交回复
热议问题