先是那个最简单的LOOP循环
loop.sql
CREATE OR REPLACE PROCEDURE loop_demo AUTHID CURRENT_USER IS l_date DATE; BEGIN l_date := SYSDATE; LOOP EXIT WHEN l_date > SYSDATE + 10; l_date := l_date + 1; DBMS_OUTPUT.PUT_LINE(l_date); END LOOP; END loop_demo; /
首先一点,我这个过程没有参数,那么我在创建那句,后面就没有括号。
还有下面 l_date := l_date + 1;
我开始使用 l_date += 1; l_date :+= 1; l_date ++;我开始试了一下这三种,后来都不成功,
才改成了现在这样的格式,看来是不支持。
BEGIN loop_demo(); END; /
这样直接执行就可以看看结果了。
2. 然后是简单的for循环,使用数值的。
for.sql
CREATE OR REPLACE PROCEDURE for_demo AUTHID CURRENT_USER IS l_date DATE; BEGIN FOR i IN 1 .. 10 LOOP l_date := SYSDATE + i; DBMS_OUTPUT.PUT_LINE(l_date); END LOOP; END for_demo; /
然后还可以使用游标的。
先用一个select语句来当IN的集合
CREATE OR REPLACE PROCEDURE for_select AUTHID CURRENT_USER IS BEGIN FOR cur IN (SELECT ENAME FROM EMP) LOOP DBMS_OUTPUT.PUT_LINE(cur.ename); END LOOP; END; /
然后for这里还有一个逆序的。这样:
CREATE OR REPLACE PROCEDURE for_reverse AUTHID CURRENT_USER IS l_date DATE; BEGIN FOR i IN REVERSE 1 .. 10 LOOP l_date := SYSDATE; l_date := l_date + i; DBMS_OUTPUT.PUT_LINE(l_date); END LOOP; END; /
下面是使用游标的for,两个可以比较一下:
DECLARE CURSOR cur IS SELECT ename FROM emp; cur_rec cur%ROWTYPE; BEGIN OPEN cur; LOOP FETCH cur INTO cur_rec; DBMS_OUTPUT.PUT_LINE(cur_rec.ename); EXIT WHEN cur%NOTFOUND; END LOOP; CLOSE cur; END; /
DECLARE CURSOR cur IS SELECT ename FROM emp; BEGIN FOR cur_rec IN cur LOOP DBMS_OUTPUT.PUT_LINE(cur_rec.ename); END LOOP; END; /
在for循环中使用游标都省略了OPEN FETCH CLOSE了。
并且可以每次执行都获得当前是多少行了。 DBMS_OUTPUT.PUT_LINE(cur%ROWCOUNT);
3. 下面是while的练习
CREATE OR REPLACE PROCEDURE while_demo AUTHID CURRENT_USER IS l_date DATE; BEGIN l_date := SYSDATE; WHILE l_date < SYSDATE + 15 LOOP l_date := l_date + 1; DBMS_OUTPUT.PUT_LINE(l_date); END LOOP; END while_demo; /
然后我在书中看到了sleep函数,这个我就想试试,但是跟我想的结果不一样。
CREATE OR REPLACE PROCEDURE while_demo AUTHID CURRENT_USER IS l_date DATE; BEGIN l_date := SYSDATE; WHILE l_date < SYSDATE + 15 LOOP l_date := l_date + 1; DBMS_OUTPUT.PUT_LINE(l_date); DBMS_LOCK.sleep(1); END LOOP; END while_demo; /
首先要用DBMS_LOCK需要有权限。在管理员下
grant execute on DBMS_LOCK to scott;
我以为是每循环一次停一下,但是实际情况却是,一直在停着,停到了15秒后,才全部打印出来。
这个是怎么回事呢?
还有一个就是下面有一个用管道的,但是我就没有成功过,一直都是在卡着,不会退出,并且明明给了sleep时间应该过了。
DECLARE pipename CONSTANT VARCHAR2(12) := 'signaler1'; result INTEGER; pipebuf VARCHAR2(64);
BEGIN result := DBMS_PIPE.create_pipe(pipename); LOOP DBMS_LOCK.sleep(5); IF DBMS_PIPE.receive_message(pipename, 0) = 0 THEN DBMS_PIPE.unpack_message(pipebuf); EXIT WHEN pipebuf = 'stop'; END IF; END LOOP; END; /
在这里有过一个问题,我当时给scott那个DBMS_PIPE的权限后,忘了进入这个用户了,直接用sys就运行了,然后退出再
用scott运行就不行了,报错,后来应该是用sys的时候把个管道创建了,scott用不上这个了就。后来我改了另一个名字。
但是,我的为什么就不能退出呢。。。
DECLARE pipename VARCHAR2(12) := 'signaler1'; result INTEGER := DBMS_PIPE.create_pipe(pipename); BEGIN DBMS_PIPE.pack_message('stop'); END; /
这个是那个停止的,但是不好用。在找问题。
我在网上看看,发现还要用上send_message,但是我用上了,还不行了,说:
PLS-00221: 'SEND_MESSAGE' is not a procedure or is undefined
这问题我还没解决。
http://wenku.baidu.com/link?url=A46JJTu6mvJ67aIZTgxFc1ASr8EosxhGhAyU1pw_tTKpeizF3txlyJt8p2ojPSmL0RjOkx5cLA0TWPSvxUqA6X87wCqnAo6McZZquMt7s0G
http://www.cnblogs.com/linjiqin/archive/2013/06/24/3152635.html
官方文档:
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_pipe.htm
我按照其实有一篇介绍的那样写了一下,还真成功了,但是remove_pipe还是报错
CREATE OR REPLACE PROCEDURE send_message AUTHID CURRENT_USER IS flag NUMBER; pipename VARCHAR2(12) := 'pipe1'; BEGIN flag := DBMS_PIPE.CREATE_PIPE(pipename); IF flag = 0 THEN DBMS_PIPE.PACK_MESSAGE('stop'); flag := DBMS_PIPE.send_message(pipename); END IF; END send_message; /
CREATE OR REPLACE PROCEDURE receive_message AUTHID CURRENT_USER IS flag NUMBER; pipename VARCHAR2(12) := 'pipe1'; message VARCHAR2(64); BEGIN LOOP flag := DBMS_PIPE.receive_message(pipename); IF flag = 0 THEN DBMS_PIPE.unpack_message(message); DBMS_OUTPUT.PUT_LINE(message); EXIT WHEN message = 'stop'; END IF;
DBMS_LOCK.sleep(10); END LOOP; END; /
执行我是用的
exec send_message();
exec receive_message();
我在写这个的时候,我忽然想到,这个和我的有什么区别呢,只是加上了flag := 这么一个开头,我就联想到了那个
CASE表达式了,这个不是过程,其实就是一个表达式,说多了,就是一个值,不能直接这么放这。
然后我去修改一下我刚才那个,应该可以现在,去试试。
修改过后,是可以了
DECLARE pipename CONSTANT VARCHAR2(12) := 'signaler1'; result INTEGER; pipebuf VARCHAR2(64); flag NUMBER; BEGIN result := DBMS_PIPE.create_pipe(pipename); LOOP DBMS_LOCK.sleep(10); IF DBMS_PIPE.receive_message(pipename) = 0 THEN DBMS_PIPE.unpack_message(pipebuf); DBMS_OUTPUT.PUT_LINE(pipebuf); flag := DBMS_PIPE.remove_pipe(pipename); EXIT WHEN pipebuf = 'stop'; END IF; END LOOP; END; /
DECLARE pipename VARCHAR2(12) := 'signaler1'; result INTEGER := DBMS_PIPE.create_pipe(pipename); flag NUMBER; BEGIN DBMS_PIPE.pack_message('stop'); flag := DBMS_PIPE.send_message(pipename, 10); END; /
我原本要放弃这个了,在网上也没有找到这样的事情,不过还是解决了。
记下错误的输出:
PLS-00221: 'REMOVE_PIPE' is not a procedure or is undefined
PLS-00221: 'SEND_MESSAGE' is not a procedure or is undefined