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_ IN NUMBER ) RETURN INTEGER IS BEGIN DBMS_LOCK.sleep(seconds => TIME_); RETURN 1; EXCEPTION WHEN OTHERS THEN RAISE; RETURN 1; END TEST_SLEEP;
and I call in this way
SELECT TEST_SLEEP(10.5) FROM DUAL
but to work I need set grant of DBMS_LOCK
to the owner of the procedure.
How I can rewrite this function without using the DBMS_LOCK.sleep
function?
SLEEP. The SLEEP procedure is added to the DBMS_SESSION package, so it is available to all sessions with no additional grants needed and no dependency on the DBMS_LOCK package. The procedure suspends the session for the specified number of seconds.
Answer: The dbms_lock. sleep procedure directs a PL/SQL anonymous code snippet or stored procedure (or function) to stop for a specified period of n seconds.
The DBMS_LOCK package provides an interface to Oracle Lock Management services. You can request a lock of a specific mode, give it a unique name recognizable in another procedure in the same or another instance, change the lock mode, and release it.
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;
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 */
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With