Я должен выполнить SQL-запрос в Oracle, она берет определенное количество времени. Таким образом, я записал эту функцию:
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;
и я звоню таким образом
SELECT TEST_SLEEP(10.5) FROM DUAL
но работать я должен установить предоставление DBMS_LOCK
владельцу процедуры.
Как я могу переписать эту функцию, не используя DBMS_LOCK.sleep
функция?
За исключением предоставления доступа к DBMS_LOCK.sleep
, это будет работать, но это ужасный взлом:
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;
Если Java установлена на вашем 11G, то вы можете сделать это в классе java и вызвать его из вашего PL/SQL, но я не уверен, что это не требует также специального гранта для вызова java.
Кажется, что java процедура/функция может работать. Но почему бы вам не скомпилировать вашу функцию под пользователем, например, под схемой приложения или учетной записью администратора, которая имеет этот грант, и просто дать вашей учетной записи разработчика право на выполнение. Таким образом, используются права разработчика.
Создайте процедуру, которая просто делает вашу блокировку и установите ее другому пользователю, которому "доверяют" dbms_lock ( USERA ), предоставьте USERA доступ к dbms_lock.
Затем просто предоставьте USERB доступ к этой функции. Затем им не нужно будет иметь доступ к DBMS_LOCK
(убедитесь, что в вашей системе нет usera и userb, прежде чем выполнять это)
Подключитесь как пользователь с правами на dbms_lock и можете создавать пользователей
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 */