`
winie
  • 浏览: 216198 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

PL/SQL的递归调用

阅读更多
已知表route,字段和内容如下:
起始节点 终止节点 距离
a b 100
a c 150
a d 200
b e 300
b f 800
e g 100
e h 300

要求找出从节点a开始能到达的所有路径

1.创建表route,插入数据

CREATE TABLE route (
  begin_node VARCHAR2(3),
  end_node VARCHAR2(3),
  distance NUMBER(4));

INSERT INTO route VALUES('a','b',100);
INSERT INTO route VALUES('a','c',150);
INSERT INTO route VALUES('a','d',200);
INSERT INTO route VALUES('b','e',300);
INSERT INTO route VALUES('b','f',800);
INSERT INTO route VALUES('e','g',300);
INSERT INTO route VALUES('e','h',300);

2.创建t_node类型

CREATE OR REPLACE TYPE t_node AS OBJECT (name VARCHAR2(3), distance NUMBER(5));

3.创建t_node_array类型,是t_node类型数组

CREATE OR REPLACE TYPE t_node_array IS TABLE OF t_node;

4.创建isloopnode(node t_node, nodes t_node_array, nodes_depth NUMBER)函数,判断node是否在nodes中出现过

CREATE OR REPLACE FUNCTION isloopnode(node t_node, nodes t_node_array, nodes_depth NUMBER)
  RETURN BOOLEAN
  IS
  i NUMBER;
  BEGIN
    FOR i IN 1..nodes_depth LOOP
      IF nodes(i).name = node.name THEN
        RETURN TRUE;
      END IF;
    END LOOP;
    RETURN FALSE;
  END;

5.创建过程printpath来打印路径

CREATE OR REPLACE PROCEDURE printpath(nodes t_node_array, nodes_depth number)
  AS
  i NUMBER(4);
  BEGIN
    FOR i IN 1..nodes_depth LOOP
     IF i<>1 THEN
       DBMS_OUTPUT.PUT('-->');
     END IF;
     DBMS_OUTPUT.PUT(nodes(i).NAME||'[');
     DBMS_OUTPUT.PUT(nodes(i).DISTANCE||']');
    END LOOP;
     DBMS_OUTPUT.PUT_LINE('');
  END;

6.遍历过程iterate

CREATE OR REPLACE PROCEDURE iterate(node IN t_node, nodesStack IN OUT t_node_array, stackDepth IN OUT NUMBER)
AS

nextNode t_node;
nextNodes t_node_array := t_node_array();
CURSOR c_route IS SELECT end_node,distance FROM route WHERE begin_node=node.name;
tempStr VARCHAR2(3);
tempInt number(4);
i number(4);
BEGIN
  --将当前节点存入路径栈中
  IF stackDepth = nodesStack.COUNT THEN
    --需要扩展栈
    nodesStack.EXTEND(1);
  END IF;
  stackDepth := stackDepth + 1;
  nodesStack(stackDepth):= node;

  --找开游标,查找后续节点
  OPEN c_route;
  FETCH c_route INTO tempStr, tempInt;

  --没有后续节点
  IF c_route%NOTFOUND THEN
    --打印出本条线路
    printpath(nodesStack, stackDepth);
    CLOSE c_route;
    --回归到上一节点
    stackDepth := stackDepth - 1;
    RETURN;
  END IF;

  --依次处理后续节点
  --先将节点存到临时数组nextNodes,以期尽快关闭游标
  WHILE c_route%FOUND LOOP
    --路程要累积起来
    nextNode := t_node(tempStr, nodesStack(stackDepth).distance + tempInt);
    --存入临时数组
    nextNodes.EXTEND(1);
    nextNodes(nextNodes.COUNT) := nextNode;
    FETCH c_route INTO tempStr, tempInt;
  END LOOP;
  CLOSE c_route;

  FOR i IN 1..nextNodes.COUNT LOOP
    nextNode := nextNodes(i);
    --判断是否与路径上的先前节点重复
    IF isloopnode(nextNode, nodesStack, stackDepth) THEN
      --打印出本条线路
      printpath(nodesStack, stackDepth);
      --回归到上一节点
      stackDepth := stackDepth - 1;
      RETURN;
    END IF;
 
    --非重复节点
    iterate(nextNode, nodesStack, stackDepth);
  END LOOP;
 
  --处理完毕本节点,回归到上一节点
  stackDepth := stackDepth - 1;
END;


7.PL/SQL调用iterate

DECLARE
  node t_node;
  nodesstack t_node_array:=t_node_array();
  stackdepth NUMBER(4);
BEGIN
  node:=t_node('A', 0);
  stackdepth:=0;
  iterate(node,nodesstack,stackdepth);
END;

8.执行结果

a[0]-->b[100]-->e[400]-->g[700]
a[0]-->b[100]-->e[400]-->h[700]
a[0]-->b[100]-->f[900]
a[0]-->c[150]
a[0]-->d[200]

分享到:
评论

相关推荐

    PL/SQL Developer 6.05注册版-1

    SQL Exporter did not export very old dates in date format - SQL Exporter could export floats with comma as decimal separator &lt;br&gt;PL/SQL Developer主要特性: PL/SQL编辑器,功能强大——该编辑器...

    PL/SQL Developer 7.1.5 注册版-3

    SQL Exporter did not export very old dates in date format - SQL Exporter could export floats with comma as decimal separator &lt;br&gt;PL/SQL Developer主要特性: PL/SQL编辑器,功能强大——该编辑器...

    PL/SQL Developer

    另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。  命令窗口——使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同...

    pl/sql developer 9 + 注册机

    另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。 命令窗口  使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同的感观...

    PL/SQL Developer v8.0.zip

    另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。 命令窗口——使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同的...

    PL/SQL Developer8.04官网程序_keygen_汉化

     至此,test_procedure存储过程已经完成,经过编译后就可以在其他PL/SQL块或者过程中调用了。  函数与过程具有很大的相似性,此处不再详述。 编辑本段 游标  游标的定义为:用游标来指代一个DML SQL操作返回的...

    PL/SQL Developer 7.1.5 注册版

    SQL Exporter did not export very old dates in date format - SQL Exporter could export floats with comma as decimal separator &lt;br&gt;PL/SQL Developer主要特性: PL/SQL编辑器,功能强大——该编辑器...

    PLSQL Developer 7.1.5

    另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。  命令窗口——使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同...

    PLSQL Developer(免安装、汉化版,很好用的) 8.0.3.1510.rar

    另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。  命令窗口——使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同...

    PLSQLDeveloper下载

    /*test_procedure可以省略*/ 至此,test_procedure存储过程已经完成,经过编译后就可以在其他PL/SQL块或者过程中调用了。函数与过程具有很大的相似性,此处不再详述。 编辑本段游标  游标的定义为:用游标来指代一...

    收获不止SQL优化

    12.1.5 避免或者减少递归调用 341 12.1.6 ROWID优化应用 347 12.2 设法避免外因影响 350 12.2.1 Hint改写确保执行计划正确 350 12.2.2 避免子查询的错误执行计划 350 12.2.3 所在环境的资源不足等问题 351 ...

    收获,不止SQL优化--抓住SQL的本质

    12.1.5 避免或者减少递归调用 341 12.1.6 ROWID优化应用 347 12.2 设法避免外因影响 350 12.2.1 Hint改写确保执行计划正确 350 12.2.2 避免子查询的错误执行计划 350 12.2.3 所在环境的资源不足等问题 351 ...

    精通SQL--结构化查询语言详解

    2.4.2 pl/sql程序结构 33 第3章 创建、修改和删除表 37 3.1 表的基础知识 37 3.1.1 表的基本结构 37 3.1.2 表的种类 38 3.2 sql数据类型 39 3.2.1 字符型数据 39 3.2.2 数字型数据 40 3.2.3 日期数据类型 41...

    精通SQL 结构化查询语言详解

    2.4.1 PL/SQL的特点  2.4.2 PL/SQL程序结构 第3章 创建、修改和删除表 3.1 表的基础知识  3.1.1 表的基本结构  3.1.2 表的种类  3.2 SQL数据类型  3.2.1 字符型数据 3.2.2 数字型数据  3.2.3 日期...

    Oraclet中的触发器

    在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块,不过有一点不同的是,触发器是隐式调用的,并不能接收参数。 触发器优点 (1)触发器能够实施的检查和操作比主键和外键约束、...

    Oracle9i的init.ora参数中文说明

    ), interpreted (然后 PL/SQL 模块将被编译为 PL/SQL 字节代码格式), debug (PL/SQL 模块将用探测调试符号来编译), non_debug。 默认值: " interpreted, non_debug " plsql_native_linker: 说明: 此参数指定链接...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    10.2.5 将子查询因子化应用到PL/SQL中 270 10.3 递归子查询 273 10.3.1 一个CONNECT BY的例子 274 10.3.2 使用RSF的例子 275 10.3.3 RSF的限制条件 276 10.3.4 与CONNECT BY的不同点 276 10.4 复制CONNECT BY...

    精髓Oralcle讲课笔记

    -- 首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba --然后,解除对scott用户的锁 alter user scott account unlock; ... --(默认全局数据库名orcl) 1、select ename, sal * 12 from ...

Global site tag (gtag.js) - Google Analytics