当前位置:首页 » 服务存储 » oracle存储过程休眠1秒
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

oracle存储过程休眠1秒

发布时间: 2022-05-20 03:16:02

‘壹’ oracle存储过程执行速度很慢是什么原因

解决办法:
你需要对你的表根据查询条件设计相应的索引,有时候根据需要可能一个表你需要建立好几个索引都是有可能的。然后再执行,你会发现原来要30几秒的现在零点几秒就可以搞定了,这跟使用游标没什么关系。游标的使用完全由你的应用需要决定,我相信能不用的你肯定不会选择使用游标处理,一般是实在没办法的情况下才选择游标去做。

你查询慢的原因是你在存储过程中执行的话,没有索引时,他会一条一条查知道把80几万条数据全部扫描一遍直到查完了你才看到一个结果,但是你在外面单独执行很快的原因是plsql他会首先去查查到几条数据就先给你返回来,所以你马上就看到结果了,但实际上查询也并没有结束,你要是数据很多的情况下你往下拉,你会发信很慢,其实查询过程根本就还没有结束。

总之写存储过程第一步是会写,第二步是要做好优化,否则当你的数据量很大的时候你的过程写的不好的话问题会马上暴露出来。

‘贰’ oracle 存储过程

1.基本结构
CREATE OR REPLACE PROCEDURE 存储过程名字
(
参数1 IN NUMBER,
参数2 IN NUMBER
) IS
变量1 INTEGER :=0;
变量2 DATE;
BEGIN
END 存储过程名字
你那个 END P_UPDATELOCKCMPINFO; 没看懂是啥意思

2.SELECT INTO STATEMENT
将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条
记录,否则抛出异常(如果没有记录抛出NO_DATA_FOUND)
例子:
BEGIN
SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx;
EXCEPTION
WHEN NO_DATA_FOUND THEN
xxxx;
END;
...

3.IF 判断
IF V_TEST=1 THEN
BEGIN
do something
END;
END IF;

4.while 循环
WHILE V_TEST=1 LOOP
BEGIN
XXXX
END;
END LOOP;

5.变量赋值
V_TEST := 123;

6.用for in 使用cursor
...
IS
CURSOR cur IS SELECT * FROM xxx;
BEGIN
FOR cur_result in cur LOOP
BEGIN
V_SUM :=cur_result.列名1+cur_result.列名2
END;
END LOOP;
END;

7.带参数的cursor
CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;
OPEN C_USER(变量值);
LOOP
FETCH C_USER INTO V_NAME;
EXIT FETCH C_USER%NOTFOUND;
do something
END LOOP;
CLOSE C_USER;

8.用pl/sql developer debug
连接数据库后建立一个Test WINDOW
在窗口输入调用SP的代码,F9开始debug,CTRL+N单步调试

简单实例,通过DBMS_OUTPUT来看结果
CREATE OR REPLACE PROCEDURE bb (lic_para IN VARCHAR2,out_para OUT VARCHAR2)
AS
temp VARCHAR2 (100);
BEGIN
SELECT lic_no
INTO temp
FROM t_vehicle_info
WHERE lic_no = lic_para;
out_para:=temp;
DBMS_OUTPUT.put_line (out_para);
END bb;
下面是调用:
begin
-- Call the procere
bb(lic_para => :lic_para,
out_para => :out_para);
end;
可以在命令行里敲sqlplus “yonghuming/mima@dbname”接着调试存储过程。但是最好用的是在pl/sql Developer工具里面用点存储过程里的TEST来调用,它能自动生成调用的语句并有栏目让你输入参数值,包括输入参数和输出参数,并把结果返回到输出参数里面,在结果栏可见,这点pl/sql Developer比TOAD要强,TOAD在存储过程上右键后点击EXECUTE Procere也可以执行,只是结果在那看我不晓得,而在pl/sql Developer按F9可以调试,ctrl+N可以单步跟踪,的确爽

‘叁’ oracle存储过程问题(急)

DBMS_Job包的用法

包含以下子过程:

Broken()过程。
change()过程。
Interval()过程。
Isubmit()过程。
Next_Date()过程。
Remove()过程。
Run()过程。
Submit()过程。
User_Export()过程。
What()过程。

1、
Broken()过程更新一个已提交的工作的状态,典型地是用来把一个已破工作标记为未破工作。
这个过程有三个参数:job 、broken与next_date。

PROCEDURE Broken (job IN binary_integer,
Broken IN boolean,
next_date IN date :=SYSDATE)

job参数是工作号,它在问题中唯一标识工作。
broken参数指示此工作是否将标记为破——TRUE说明此工作将标记为破,而FLASE说明此工作将标记为未破。
next_date参数指示在什么时候此工作将再次运行。此参数缺省值为当前日期和时间。

2、
Change()过程用来改变指定工作的设置。
这个过程有四个参数:job、what 、next_date与interval。

PROCEDURE Change (job IN binary_integer,
What IN varchar2,
next_date IN date,
interval IN varchar2)

此job参数是一个整数值,它唯一标识此工作。
What参数是由此工作运行的一块PL/SQL代码块。
next_date参数指示何时此工作将被执行。
interval参数指示一个工作重执行的频度。

3、
Interval()过程用来显式地设置重执行一个工作之间的时间间隔数。
这个过程有两个参数:job与interval。

PROCEDURE Interval (job IN binary_integer,
Interval IN varchar2)

job参数标识一个特定的工作。interval参数指示一个工作重执行的频度。

4、
ISubmit()过程用来用特定的工作号提交一个工作。
这个过程有五个参数:job、what、next_date、interval与no_parse。

PROCEDURE ISubmit (job IN binary_ineger,
What IN varchar2,
next_date IN date,
interval IN varchar2,
no_parse IN booean:=FALSE)

这个过程与Submit()过程的唯一区别在于此job参数作为IN型参数传递且包括一个
由开发者提供的工作号。如果提供的工作号已被使用,将产生一个错误。

5、
Next_Date()过程用来显式地设定一个工作的执行时间。这个过程接收两个参数:job与next_date。

PROCEDURE Next_Date(job IN binary_ineger,
next_date IN date)

job标识一个已存在的工作。next_date参数指示了此工作应被执行的日期与时间。

6、
Remove()过程来删除一个已计划运行的工作。这个过程接收一个参数:

PROCEDURE Remove(job IN binary_ineger);

job参数唯一地标识一个工作。这个参数的值是由为此工作调用Submit()过程返回的job参数的值。
已正在运行的工作不能由调用过程序删除。

7、
Run()过程用来立即执行一个指定的工作。这个过程只接收一个参数:

PROCEDURE Run(job IN binary_ineger)

job参数标识将被立即执行的工作。

8、
使用Submit()过程,工作被正常地计划好。
这个过程有五个参数:job、what、next_date、interval与no_parse。

PROCEDURE Submit ( job OUT binary_ineger,
What IN varchar2,
next_date IN date,
interval IN varchar2,
no_parse IN booean:=FALSE)

job参数是由Submit()过程返回的binary_ineger。这个值用来唯一标识一个工作。
what参数是将被执行的PL/SQL代码块。
next_date参数指识何时将运行这个工作。
interval参数何时这个工作将被重执行。
no_parse参数指示此工作在提交时或执行时是否应进行语法分析——TRUE
指示此PL/SQL代码在它第一次执行时应进行语法分析,
而FALSE指示本PL/SQL代码应立即进行语法分析。

9、
User_Export()过程返回一个命令,此命令用来安排一个存在的工作以便此工作能重新提交。
此程序有两个参数:job与my_call。

PROCEDURE User_Export(job IN binary_ineger,
my_call IN OUT varchar2)

job参数标识一个安排了的工作。my_call参数包含在它的当前状态重新提交此工作所需要
的正文。

10、
What()过程应许在工作执行时重新设置此正在运行的命令。这个过程接收两个参数:job与what。

PROCEDURE What (job IN binary_ineger,
What IN OUT varchar2)

job参数标识一个存在的工作。what参数指示将被执行的新的PL/SQL代码。

一个简单例子:

创建测试表
SQL> create table a(a date);

表已创建。

创建一个自定义过程
SQL> create or replace procere test as
2 begin
3 insert into a values(sysdate);
4 end;
5 /

过程已创建。

创建JOB
SQL> variable job1 number;
SQL>
SQL> begin
2 dbms_job.submit(:job1,'test;',sysdate,'sysdate+1/1440'); --每天1440分钟,即一分钟运行test过程一次
3 end;
4 /

PL/SQL 过程已成功完成。

运行JOB
SQL> begin
2 dbms_job.run(:job1);
3 end;
4 /

PL/SQL 过程已成功完成。

SQL> select to_char(a,'yyyy/mm/dd hh24:mi:ss') 时间 from a;

时间
-------------------
2001/01/07 23:51:21
2001/01/07 23:52:22
2001/01/07 23:53:24

删除JOB
SQL> begin
2 dbms_job.remove(:job1);
3 end;
4 /

PL/SQL 过程已成功完成。

delete from BDZHB where SBH like '%X%' 这个sql就是查询带有X的全部记录

‘肆’ oracle存储过程

create table dept
(deptno number,
dname varchar2(20),
loc varchar2(20)
)
1.如果你是取出单个的,你可以定义一个或者多个变量,将取出的值赋给变量
例如:

create or replace procere dept_procere(a in varchar2)
is
v_no number;
v_a varchar2(20);
begin
select a.deptno,a.loc into v_no,v_a
from dept a
where a.dname=a;
dbms_output.put_line('学号为:'||v_no||);
end;
2.如果你取出的是一个结果集,你可以用游标(一个简单的例子)
create or replace procere dept_procere(a in varchar2,v_a out dept%rowtype)
is
--声明游标
cursor c_de(a in varchar2)
is select * from dept where dname=a;
begin
--打开游标,对其中找到的记录进行遍历
open c_de(a);
loop
fetch c_de into v_a;
exit when c_de%notfound;
end loop;
close c_de;
dbms_output.put_line('deptno:'||v_a.deptno);
dbms_output.put_line('dname:'||v_a.dname);
dbms_output.put_line('loc:'||v_a.loc);
end;

3.可注意:在创建存储过程的时候加上or replace,如果遇到重名的存储过程将替换掉!
4.定义变量后面记得加上分号
5.oracle中可以对它直接赋值,可不用set, v_a:='a';
(6.给变量赋值的时候注意它的数据类型 a要单引号)
7.如果你这存储过程是将参数赋值给一个你定义的变量的话,那这样你不觉得是多此一举么?一般将参数赋值给你定义的变量的话,可以进行数据类型转换!可在此存储过程中,没发现它的用处
8.你取出来的数据,要放在变量或是游标中,显示出来,不然你写出来的存储过程有什么用呢?所以 select ...into ...
9.我也是刚学oracle的,希望可以互相学习一下,呵呵!上面的如有错误希望可以告诉我一下啊

‘伍’ Oracle数据库存储过程中要写一个睡眠时间,怎么实现

DBMS_LOCK.sleep (5);

没有用过,你自己试

‘陆’ oracle中怎么实现进程的睡眠和唤醒

1 Linux进程的睡眠和唤醒
在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在一个运行队列中,一个就绪进程的状 态标志位为TASK_RUNNING。一旦一个运行中的进程时间片用完, Linux 内核的调度器会剥夺这个进程对CPU的控制权,并且从运行队列中选择一个合适的进程投入运行。
当然,一个进程也可以主动释放CPU的控制权。函数 schele()是一个调度函数,它可以被一个进程主动调用,从而调度其它进程占用CPU。一旦这个主动放弃CPU的进程被重新调度占用 CPU,那么它将从上次停止执行的位置开始执行,也就是说它将从调用schele()的下一行代码处开始执行。
有时候,进程需要等待直到某个特定的事件发生,例如设备初始化完成、I/O 操作完成或定时器到时等。在这种情况下,进程则必须从运行队列移出,加入到一个等待队列中,这个时候进程就进入了睡眠状态。
Linux 中的进程睡眠状态有两种:一种是可中断的睡眠状态,其状态标志位TASK_INTERRUPTIBLE;
另一种是不可中断 的睡眠状态,其状态标志位为TASK_UNINTERRUPTIBLE。可中断的睡眠状态的进程会睡眠直到某个条件变为真,比如说产生一个硬件中断、释放 进程正在等待的系统资源或是传递一个信号都可以是唤醒进程的条件。不可中断睡眠状态与可中断睡眠状态类似,但是它有一个例外,那就是把信号传递到这种睡眠 状态的进程不能改变它的状态,也就是说它不响应信号的唤醒。不可中断睡眠状态一般较少用到,但在一些特定情况下这种状态还是很有用的,比如说:进程必须等 待,不能被中断,直到某个特定的事件发生。
在现代的Linux操作系统中,进程一般都是用调用schele()的方法进入睡眠状态的,下面的代码演
示了如何让正在运行的进程进入睡眠状态。
sleeping_task = current;
set_current_state(TASK_INTERRUPTIBLE);
schele();
func1();
/* Rest of the code ... */
在第一个语句中,程序存储了一份进程结构指针sleeping_task,current 是一个宏,它指向正在执行
的进程结构。set_current_state()将该进程的状态从执行状态TASK_RUNNING 变成睡眠状态
TASK_INTERRUPTIBLE。 如果schele()是被一个状态为TASK_RUNNING 的进程调度,那么schele()将调度另外一个进程占用CPU;如果schele()是被一个状态为TASK_INTERRUPTIBLE 或TASK_UNINTERRUPTIBLE 的进程调度,那么还有一个附加的步骤将被执行:当前执行的进程在另外一个进程被调度之前会被从运行队列中移出,这将导致正在运行的那个进程进入睡眠,因为 它已经不在运行队列中了。
我们可以使用下面的这个函数将刚才那个进入睡眠的进程唤醒。
wake_up_process(sleeping_task);
在调用了wake_up_process()以后,这个睡眠进程的状态会被设置为TASK_RUNNING,而且调度器
会把它加入到运行队列中去。当然,这个进程只有在下次被调度器调度到的时候才能真正地投入运行。
2 无效唤醒
几乎在所有的情况下,进程都会在检查了某些条件之后,发现条件不满足才进入睡眠。可是有的时候
进程却会在 判定条件为真后开始睡眠,如果这样的话进程就会无限期地休眠下去,这就是所谓的无效唤醒问题。在操作系统中,当多个进程都企图对共享数据进行某种处理,而 最后的结果又取决于进程运行的顺序时,就会发生竞争条件,这是操作系统中一个典型的问题,无效唤醒恰恰就是由于竞争条件导致的。
设想有两个进程A 和B,A 进程正在处理一个链表,它需要检查这个链表是否为空,如果不空就对链
表里面的数据进行一些操作,同时B进程也在往这个链表添加节点。当这个链表是空的时候,由于无数据可操作,这时A进程就进入睡眠,当B进程向链表里面添加了节点之后它就唤醒A 进程,其代码如下:
A进程:
1 spin_lock(&list_lock);
2 if(list_empty(&list_head)) {
3 spin_unlock(&list_lock);
4 set_current_state(TASK_INTERRUPTIBLE);
5 schele();
6 spin_lock(&list_lock);
7 }
8
9 /* Rest of the code ... */
10 spin_unlock(&list_lock);
B进程:
100 spin_lock(&list_lock);
101 list_add_tail(&list_head, new_node);
102 spin_unlock(&list_lock);
103 wake_up_process(processa_task);
这里会出现一个问题,假如当A进程执行到第3行后第4行前的时候,B进程被另外一个处理器调度
投 入运行。在这个时间片内,B进程执行完了它所有的指令,因此它试图唤醒A进程,而此时的A进程还没有进入睡眠,所以唤醒操作无效。在这之后,A 进程继续执行,它会错误地认为这个时候链表仍然是空的,于是将自己的状态设置为TASK_INTERRUPTIBLE然后调用schele()进入睡 眠。由于错过了B进程唤醒,它将会无限期的睡眠下去,这就是无效唤醒问题,因为即使链表中有数据需要处理,A 进程也还是睡眠了。
3 避免无效唤醒
如何避免无效唤醒问题呢?我们发现无效唤醒主要发生在检查条件之后和进程状态被设置为睡眠状
态之前, 本来B进程的wake_up_process()提供了一次将A进程状态置为TASK_RUNNING 的机会,可惜这个时候A进程的状态仍然是TASK_RUNNING,所以wake_up_process()将A进程状态从睡眠状态转变为运行状态的努力 没有起到预期的作用。要解决这个问题,必须使用一种保障机制使得判断链表为空和设置进程状态为睡眠状态成为一个不可分割的步骤才行,也就是必须消除竞争条 件产生的根源,这样在这之后出现的wake_up_process ()就可以起到唤醒状态是睡眠状态的进程的作用了。
找到了原因后,重新设计一下A进程的代码结构,就可以避免上面例子中的无效唤醒问题了。
A进程:
1 set_current_state(TASK_INTERRUPTIBLE);
2 spin_lock(&list_lock);
3 if(list_empty(&list_head)) {
4 spin_unlock(&list_lock);
5 schele();
6 spin_lock(&list_lock);
7 }
8 set_current_state(TASK_RUNNING);
9
10 /* Rest of the code ... */
11 spin_unlock(&list_lock);
可以看到,这段代码在测试条件之前就将当前执行进程状态转设置成TASK_INTERRUPTIBLE了,并且在链表不为空的情况下又将自己置为TASK_RUNNING状态。这样一来如果B进程在A进程进程检查
了链表为空以后调用wake_up_process(),那么A进程的状态就会自动由原来TASK_INTERRUPTIBLE
变成TASK_RUNNING,此后即使进程又调用了schele(),由于它现在的状态是TASK_RUNNING,所以仍然不会被从运行队列中移出,因而不会错误的进入睡眠,当然也就避免了无效唤醒问题。
4 Linux内核的例子
在Linux操作系统中,内核的稳定性至关重要,为了避免在Linux操作系统内核中出现无效唤醒问题,
Linux内核在需要进程睡眠的时候应该使用类似如下的操作:
/* ‘q’是我们希望睡眠的等待队列 */
DECLARE_WAITQUEUE(wait,current);
add_wait_queue(q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
/* 或TASK_INTERRUPTIBLE */
while(!condition) /* ‘condition’ 是等待的条件*/
schele();
set_current_state(TASK_RUNNING);
remove_wait_queue(q, &wait);
上面的操作,使得进程通过下面的一系列步骤安全地将自己加入到一个等待队列中进行睡眠:首先调
用DECLARE_WAITQUEUE ()创建一个等待队列的项,然后调用add_wait_queue()把自己加入到等待队列中,并且将进程的状态设置为 TASK_INTERRUPTIBLE 或者TASK_INTERRUPTIBLE。然后循环检查条件是否为真:如果是的话就没有必要睡眠,如果条件不为真,就调用schele()。当进程 检查的条件满足后,进程又将自己设置为TASK_RUNNING 并调用remove_wait_queue()将自己移出等待队列。
从上面可以看到,Linux的内核代码维护者也是在进程检查条件之前就设置进程的状态为睡眠状态,
然后才循环检查条件。如果在进程开始睡眠之前条件就已经达成了,那么循环会退出并用set_current_state()将自己的状态设置为就绪,这样同样保证了进程不会存在错误的进入睡眠的倾向,当然也就不会导致出现无效唤醒问题。
下面让我们用linux 内核中的实例来看看Linux 内核是如何避免无效睡眠的,这段代码出自Linux2.6的内核(linux-2.6.11/kernel/sched.c: 4254):
4253 /* Wait for kthread_stop */
4254 set_current_state(TASK_INTERRUPTIBLE);
4255 while (!kthread_should_stop()) {
4256 schele();
4257 set_current_state(TASK_INTERRUPTIBLE);
4258 }
4259 __set_current_state(TASK_RUNNING);
4260 return 0;
上面的这些代码属于迁移服务线程migration_thread,这个线程不断地检查kthread_should_stop(),
直 到kthread_should_stop()返回1它才可以退出循环,也就是说只要kthread_should_stop()返回0该进程就会一直睡 眠。从代码中我们可以看出,检查kthread_should_stop()确实是在进程的状态被置为TASK_INTERRUPTIBLE后才开始执行 的。因此,如果在条件检查之后但是在schele()之前有其他进程试图唤醒它,那么该进程的唤醒操作不会失效。
小结
通过上面的讨论,可以发现在Linux 中避免进程的无效唤醒的关键是在进程检查条件之前就将进程的
状态置为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE,并且如果检查的条件满足的话就应该
将其状态重新设置为TASK_RUNNING。这样无论进程等待的条件是否满足, 进程都不会因为被移出就绪队列而错误地进入睡眠状态,从而避免了无效唤醒问题。

‘柒’ oracle的存储过程

1.存储过程可以使得程序执行效率更高、安全性更好,因为过程建立之后 已经编译并且储存到数据库,直接写sql就需要先分析再执行因此过程效率更高,直接写sql语句会带来安全性问题,如:sql注入
2.建立过程不会很耗系统资源,因为过程只是在调用才执行。
3.存储过程可以用于降低网络流量,存储过程代码直接存储于数据库中,所以不会产生大量T-sql语句的代码流量。

4.使用存储过程使您能够增强对执行计划的重复使用,由此可以通过使用远程过程调用 (RPC) 处理服务器上的存储过程而提高性能。RPC 封装参数和调用服务器端过程的方式使引擎能够轻松地找到匹配的执行计划,并只需插入更新的参数值。

5.可维护性高,更新存储过程通常比更改、测试以及重新部署程序集需要较少的时间和精力。

6.代码精简一致,一个存储过程可以用于应用程序代码的不同位置。

7.增强安全性:
a、通过向用户授予对存储过程(而不是基于表)的访问权限,它们可以提供对特定数据的访问;
b、提高代码安全,防止 SQL注入(但未彻底解决,例如,将数据操作语言--DML,附加到输入参数);
c、SqlParameter 类指定存储过程参数的数据类型,作为深层次防御性策略的一部分,可以验证用户提供的值类型(但也不是万无一失,还是应该传递至数据库前得到附加验证)。

缺点就是:
1、大量的利用过程,会对服务器压力比较大。

‘捌’ oracle 怎么存储过程在执行中等待5秒

dbms_lock.sleep(5000)

‘玖’ Oracle中存储过程如何设置等待特定时长之后再执行sql

oraclejob有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务。。
每秒钟执行次Interval=>sysdate+1/(24*60*60),如果改成sysdate+10/(24*60*60)就是10秒钟执行,每分钟执行Interval=>TRUNC(sysdate,'mi')+1/(24*60)如果改成TRUNC(sysdate,'mi')+10/(24*60)就是每10分执行次每天定时执行例如:每天的凌晨1点执行Interval=>TRUNC(sysdate)+1+1/(24)。

‘拾’ Oracle存储过程长时间不跳出过程

对就是在数据库里,你可以用pl/sql连接oracle,看到里面有个PROCEDURE,可以在这里找到你写的存储过程了