ORACLE中的睡眠功能

Sal*_*dor 30 sql oracle plsql oracle11g

我需要在ORACLE中执行SQL查询需要一定的时间.所以我写了这个函数:

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;
Run Code Online (Sandbox Code Playgroud)

我以这种方式打电话

SELECT TEST_SLEEP(10.5) FROM DUAL
Run Code Online (Sandbox Code Playgroud)

但要工作,我需要设置授予DBMS_LOCK程序的所有者.

如何在不使用该功能的情况下重写此DBMS_LOCK.sleep功能?

OMG*_*ies 41

如果没有授予权限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;
Run Code Online (Sandbox Code Playgroud)

  • 虽然它的工作原理将消耗**很多的CPU. (26认同)
  • 我同意文森特...这会奏效,但这是一个可怕的可怕想法. (8认同)
  • @Salvador:可能有更好的答案 - 这个有效,但我不希望表现那么好. (5认同)
  • 平等是危险的,你可以遇到跳过价值问题.你应该使用< (5认同)
  • 啊!!!我的天啊!!!这可能会降低整个数据库的性能,因为它会消耗大量 CPU !!!由于这样的“解决方案”,我们在庞大的企业环境中遇到了问题。我不推荐。事实上,敲诈你的数据库管理员来获得这个授权更容易:嘿,或者你给我这个授权,否则我将使用无限循环......无论你想要什么。这肯定会奏效。 (2认同)

Mat*_*son 22

创建一个只执行锁定并将其安装到使用dbms_lock(USERA)"信任"的其他用户的过程,授予USERA访问dbms_lock的权限.

然后只授予USERB访问此功能的权限.然后他们不需要能够访问DBMS_LOCK

(在运行之前,请确保系统中没有usera和userb)

以具有dbms_lock的grant privs的用户身份进行连接,并可以创建用户

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 */
Run Code Online (Sandbox Code Playgroud)


met*_*hbe 8

如果在"sqlplus"中执行,则可以执行主机操作系统命令"sleep":

!sleep 1
Run Code Online (Sandbox Code Playgroud)

要么

host sleep 1
Run Code Online (Sandbox Code Playgroud)


dom*_*nik 8

有一篇关于这个主题的好文章:PL/SQL: Sleep without using DBMS_LOCK帮助了我。我使用了封装在自定义包中的选项 2。建议的解决方案是:

选项 1:APEX_UTIL.sleep

如果安装了 APEX,您可以使用公开可用的 APEX_UTIL 包中的“PAUSE”过程。

示例 – “等待 5 秒”:

SET SERVEROUTPUT ON ;
BEGIN
    DBMS_OUTPUT.PUT_LINE('Start ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
    APEX_UTIL.PAUSE(5);
    DBMS_OUTPUT.PUT_LINE('End   ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
END;
/
Run Code Online (Sandbox Code Playgroud)

选项 2:java.lang.Thread.sleep

另一种选择是使用 Java 类“Thread”中的方法“sleep”,您可以通过提供一个简单的 PL/SQL 包装过程轻松使用该方法:

注意:请记住,“Thread.sleep”使用毫秒!

--- create ---
CREATE OR REPLACE PROCEDURE SLEEP (P_MILLI_SECONDS IN NUMBER) 
AS LANGUAGE JAVA NAME 'java.lang.Thread.sleep(long)';

--- use ---
SET SERVEROUTPUT ON ;
BEGIN
    DBMS_OUTPUT.PUT_LINE('Start ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
    SLEEP(5 * 1000);
    DBMS_OUTPUT.PUT_LINE('End   ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
END;
/
Run Code Online (Sandbox Code Playgroud)


Luk*_*zda 8

在Oracle 18c中,您可以使用DBMS_SESSION.SLEEP过程:

此过程将会话挂起指定的时间段。

DBMS_SESSION.SLEEP (seconds  IN NUMBER)
Run Code Online (Sandbox Code Playgroud)

DBMS_SESSION.sleep适用于所有会话,无需额外的资助。请注意,DBMS_LOCK.sleep已弃用。

如果您需要简单的查询睡眠,则可以使用WITH FUNCTION

WITH FUNCTION my_sleep(i NUMBER)
RETURN NUMBER
BEGIN
    DBMS_SESSION.sleep(i);
    RETURN i;
END;
SELECT my_sleep(3) FROM dual;
Run Code Online (Sandbox Code Playgroud)


Mac*_*uch 5

过程包装的 Java 代码怎么样?简单且运行良好。

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)';
Run Code Online (Sandbox Code Playgroud)