`
xurichusheng
  • 浏览: 341636 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

pl/sql 函数的递归调用(时间操作)

阅读更多

 

工具 : PLSQL Developer

 

要求:

      给定一个时间(date 类型, yyyy-MM-dd HH:mm:ss),求过了n个星期后,此时间的下一个月的时间.

 

CREATE OR REPLACE FUNCTION FN_RECURSIVE_DATE(EXEC_TIME IN DATE,   -- 执行时间
                                             V_CYCLE   IN NUMBER, -- n周
                                             OUT_DATE  OUT DATE)  -- 执行时间执行n周后的下一个月时间
  RETURN DATE AS

  /*按周期赠送,按周的递归函数,找到配置的执行时间的下一个月*/

  V_EXEC_DAY      NUMBER(2); -- 执行时间EXEC_TIME中的天
  V_EXEC_MONTH    NUMBER(2); -- 执行时间EXEC_TIME中的月份
  V_EXEC_YEAR     VARCHAR2(4); -- 执行时间EXEC_TIME中的年份
  V_DAYS          NUMBER(4); -- 总天数
  V_STR_EXEC_TIME VARCHAR2(20); -- 执行时间EXEC_TIME的字符串表示方式
  V_SPACE_INDEX   NUMBER(2); -- 执行时间EXEC_TIME中空格所在索引
  V_OTHERS_TIME   VARCHAR2(20); -- EXEC_TIME的格式' HH:mm:ss'
  V_MAX_DAY       NUMBER(2); -- 某个月的最大天数
  V_CUR_YEAR      VARCHAR2(4); -- 当前年份
  V_CUR_MONTH     NUMBER(2); -- 当前月份
  V_N_EXEC_YEAR   NUMBER(4); -- V_EXEC_YEAR 的number格式
  V_NEXT_MONTH    NUMBER(2); -- 下一月
  V_N_CUR_YEAR    NUMBER(4); -- v_cur_year 的number格式
BEGIN
  -- 取出execTime的day
  V_EXEC_DAY := FN_GET_DAY_OF_DATE(EXEC_TIME, V_EXEC_DAY);
  -- 取出执行时间execTime中的月份
  V_EXEC_MONTH := F_GET_MONTH(EXEC_TIME, V_EXEC_MONTH);
  -- execTime 的年份
  V_EXEC_YEAR := FN_GET_YEAR_OF_DATE(EXEC_TIME, V_EXEC_YEAR);
  -- n周的天数+执行时间中的day
  V_DAYS := V_EXEC_DAY + V_CYCLE * 7;
  -- 将exec_time转成string格式
  V_STR_EXEC_TIME := TO_CHAR(EXEC_TIME, 'yyyy-mm-dd hh24:mi:ss');
  -- 找出exec_time中空格的位置
  V_SPACE_INDEX := INSTR(V_STR_EXEC_TIME, ' ', 1, 1);
  -- ' HH:mm:ss'
  V_OTHERS_TIME := SUBSTR(V_STR_EXEC_TIME, V_SPACE_INDEX);
  -- 某个月的最大天数
  V_MAX_DAY := FN_MAXDAYOFMONTH(V_EXEC_MONTH, V_EXEC_YEAR, V_MAX_DAY);

  IF V_DAYS > V_MAX_DAY THEN
    /* 如果总天数大于该月的最大天数 */

    V_EXEC_MONTH := V_EXEC_MONTH + 1;

    IF V_EXEC_MONTH > 12 THEN
      V_EXEC_MONTH := 1;
      V_EXEC_YEAR  := TO_CHAR(TO_NUMBER(V_EXEC_YEAR) + 1);
    END IF;
    -- end of IF V_EXEC_MONTH > 12

    V_EXEC_DAY := V_DAYS - V_MAX_DAY;

    -- 获取当前月份
    V_CUR_MONTH := F_GET_MONTH(SYSDATE, V_CUR_MONTH);

    -- 执行年份的number格式
    V_N_EXEC_YEAR := TO_NUMBER(V_EXEC_YEAR);

    V_NEXT_MONTH := V_CUR_MONTH + 1;

    IF V_NEXT_MONTH > 12 THEN
      V_NEXT_MONTH  := 1;
      V_N_EXEC_YEAR := V_N_EXEC_YEAR + 1;
    END IF;
    -- end of IF v_next_month > 12

    -- 获取当前年份
    V_CUR_YEAR := FN_GET_YEAR_OF_DATE(SYSDATE, V_CUR_YEAR);

    V_N_CUR_YEAR := TO_NUMBER(V_CUR_YEAR);

    IF (V_N_CUR_YEAR = V_N_EXEC_YEAR OR V_N_CUR_YEAR + 1 = V_N_EXEC_YEAR) AND
       V_NEXT_MONTH = V_EXEC_MONTH THEN
      /* 是下一个月 */
      V_STR_EXEC_TIME := V_EXEC_YEAR || '-' || V_EXEC_MONTH || '-' ||
                         V_EXEC_DAY || V_OTHERS_TIME;

      OUT_DATE := TO_DATE(V_STR_EXEC_TIME, 'yyyy-mm-dd hh24:mi:ss');

      RETURN OUT_DATE;

    END IF;

  ELSE
    /* 没到下一个月 */ 
    -- 这里的day写的是 V_DAYS (相加后的总天数) , 不然会出现死循环
    V_STR_EXEC_TIME := V_EXEC_YEAR || '-' || V_EXEC_MONTH || '-' ||
                       V_DAYS || V_OTHERS_TIME;

    OUT_DATE := TO_DATE(V_STR_EXEC_TIME, 'yyyy-mm-dd hh24:mi:ss');
    
    -- 递归调用
    RETURN FN_RECURSIVE_DATE(OUT_DATE, V_CYCLE, OUT_DATE);

  END IF;
  -- end of if V_DAYS > V_MAX_DAY

EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('execute FN_RECURSIVE_DATE fail!' || SQLERRM);
END;
/
 

 

执行:

  在工具 PLSQL Developer 的Command Window 中输入以下的代码:

 

VAR v_date DATE;
EXEC :v_date := FN_RECURSIVE_DATE(SYSDATE,2,:v_date);
 

执行结果如下所示:

 


 

  • 大小: 17.1 KB
分享到:
评论

相关推荐

    oracle PL/SQL测试题目和详细答案

    - **C、函数不能递归调用**:错误,函数可以递归调用,只要不超过系统限制。 - **D、以上说法都不对**:错误,选项B正确。 **4. 有一产品表(编号,名称,价格,数量,所属分类),下列语法不正确的是?** - **...

    pl/sql详解(含可运行实例)

    在"第七章.doc"中,你可能会学习到关于PL/SQL的更高级主题,比如递归、游标的高级用法、存储过程的参数传递、复合类型以及PL/SQL与数据库并发控制的机制。每个实例都是精心设计的,旨在帮助你理解和掌握这些概念,...

    pl/sql学习基础

    §1.2.2 PL/SQL的好处主要体现在以下几个方面:1) 提高代码复用性,通过定义函数和过程,可以将常用操作封装起来;2) 提供更高级的数据控制,如循环、条件判断和异常处理;3) 提升性能,因为PL/SQL代码在服务器端...

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

    SQL基本命令 PL/SQL使用的数据库操作语言还是基于SQL的,所以熟悉SQL是进行PL/SQL编程的基础。SQL语言的分类情况大致如下:  1) 数据定义语言(DDL):Create,Drop,Grant,Revoke,…  2) 数据操纵语言(DML):...

    Oracle PL SQL专家指南_高级PLSQL解决方案的设计与开发

    - **递归调用**:理解如何在过程或函数中使用递归调用来解决复杂问题。 3. **游标和集合** - **游标**:使用游标处理单行或多行结果集,以实现动态查询。 - **集合类型**:如VARRAY和NESTED TABLE,用于存储一组...

    oracle pl_sql编程

    PL/SQL用于在Oracle数据库中创建存储过程、函数、触发器和包,提供高效且安全的数据处理。 2. **基本结构**:PL/SQL由声明部分(DECLARE)、执行部分(BEGIN...END)和异常处理部分(EXCEPTION)组成。声明部分定义...

    Oracle PL-SQL语言初级教程

    你可以直接在SQL查询中使用PL/SQL函数,这使得数据库操作更加灵活。 触发器是另一种重要的PL/SQL元素,它是在特定数据库事件(如INSERT、UPDATE或DELETE)发生时自动执行的代码段。触发器可以用来实施复杂的业务...

    McGraw-Hill - Oracle Database 11g PLSQL Programming (Mar 2008)

    2. **PL/SQL块**:包括匿名块、子程序(函数和过程)以及包的创建和调用。学习如何定义输入输出参数,理解作用域规则,以及如何在PL/SQL中使用SQL语句。 3. **游标**:用于处理单行或多行结果集,是PL/SQL中进行...

    Oracle PL SQL语言基础

    - 递归:通过在过程或函数内部调用自身实现递归操作。 3. 子程序: - 过程(PROCEDURE):无返回值的子程序,用于执行一系列操作。 - 函数(FUNCTION):返回一个特定值的子程序,可以被其他PL/SQL代码或SQL查询...

    Oracle 递归函数介绍

    Oracle 递归函数是一种特殊的PL/SQL函数,可以用于解决复杂的树形结构查询问题。递归函数可以自我调用,以便遍历树形结构的每个节点,直到达到停止条件。 在 Oracle 中,递归函数的定义语法如下所示: ```sql ...

    PLSQLDeveloper下载

    因此可以在将申明发送到甲骨文系统去执行之前使用PL/SQL区段和副程序来组合SQL申明,没有PL/SQL,甲骨文需要就每次处理SQL申明,在网络环境中,这将影响交通流量,而且增加响应时间。PL/SQL区段只被编译一次并且以可...

    Oracle PLSQL测试题与答案(绝对经典).docx

    - 函数可以递归调用,但需谨慎处理避免无限循环。 4. **SQL查询语句**: - 选择题中的D选项是错误的,因为它试图在`GROUP BY`子句中使用聚合函数`MAX()`。 5. **触发器**: - 触发器可以在表上创建`INSTEAD OF`...

    oracle 脚本_自己备用

    - 递归:可以使用自身调用来实现递归功能。 4. **PL/SQL块**: - 基本块:DECLARE-BEGIN-END结构,用于定义变量和执行语句。 - 动态块:EXECUTE IMMEDIATE语句用于动态执行SQL语句。 - 匿名块:未命名的PL/SQL...

    SQL-e-PL-SQL---ORACLE:开始培训ORACLE数据库

    4. PL/SQL基础:了解PL/SQL的语法结构,如声明变量、执行流程控制、处理异常,以及如何定义和调用存储过程和函数。 5. PL/SQL进阶:学习游标的使用,以及如何在PL/SQL中进行文件I/O和数据库连接操作。理解PL/SQL块...

    oracle存储过程超详细使用手册

    9. **递归**:存储过程可以递归调用自身,但需要谨慎以避免无限循环。 10. **包(Package)**:包是将相关过程和函数组织在一起的结构,可以提高代码的模块化和重用性。包包含公共部分(可以被所有用户访问)和私有...

    oraclesql高级编程 随书脚本

    存储过程和函数是PL/SQL的核心部分,它们允许将一系列操作封装在一起,提高代码复用性和执行效率。通过实践脚本中的例子,你可以学习如何创建、调用和管理自定义的存储过程和函数。 5. **触发器** 触发器是在特定...

    Oracle_PLSQL测试题与答案(绝对经典).docx

    函数可以递归调用,但需要谨慎处理以避免无限循环(C错误)。 4. **SQL 查询**: - 选项D不正确,因为 `max()` 函数不能直接在 `WHERE` 子句中使用,而应在 `HAVING` 子句中使用。 5. **触发器**: - 可以在表上...

Global site tag (gtag.js) - Google Analytics