Oracle PL/SQL程序设计 第五版 上册 第五章 用循环进行迭代处理

  1. 先是那个最简单的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







你可能感兴趣的:(Oracle PL/SQL程序设计 第五版 上册 第五章 用循环进行迭代处理)