`
xurichusheng
  • 浏览: 335138 次
  • 性别: 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
分享到:
评论

相关推荐

    PL/SQL Developer v8.0.zip

    PL/SQL Developer是一个集成开发环境,专门面向Oracle数据库存储程序单元的开发。如今,有越来越多的商业逻辑和应用逻辑转向了Oracle Server,因此,PL/SQL编程也成了整个开发过程的一个重要组成部分。PL/SQL ...

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

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

    PLSQLDeveloper下载

    因此可以在将申明发送到甲骨文系统去执行之前使用PL/SQL区段和副程序来组合SQL申明,没有PL/SQL,甲骨文需要就每次处理SQL申明,在网络环境中,这将影响交通流量,而且增加响应时间。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 结构化查询语言详解

    《精通SQ:结构化查询语言详解》全面讲解SQL语言,提供317个典型应用,读者可以随查随用,针对SQL Server和Oracle进行讲解,很有代表性。 全书共包括大小实例317个,突出了速学速查的特色。《精通SQ:结构化查询语言...

    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...

    Visual C++ 2005入门经典--源代码及课后练习答案

    5.4 递归函数调用 239 5.5 C++/CLI编程 241 5.5.1 接受数量可变实参的函数 242 5.5.2 main( )的实参 243 5.6 小结 244 5.7 练习 245 第6章 程序结构(2) 246 6.1 函数指针 246 6.1.1 声明函数指针 ...

    精髓Oralcle讲课笔记

    --(函数round() 进行四舍五入操作) 35、select round(23.232, 2) from dual; --(四舍五入后保留的小数位数 0 个位 -1 十位) 36、select to_char(sal, '$99,999.9999')from emp; --(加$符号加入千位分隔符,保留...

    oracle+proc中文.pdf

    3.6.10 可以在递归函数中嵌入SQL么? ..................................................................................10 3.6.11 我可以在任意版本的Oracle中使用任意版本的预编译器么?.........................

    Java学习笔记-个人整理的

    {1.11.3}递归调用}{41}{subsection.1.11.3} {1.12}Java API}{41}{section.1.12} {1.13}Linux命令}{41}{section.1.13} {1.13.1}基本查看、移动}{41}{subsection.1.13.1} {1.13.2}权限}{42}{subsection.1.13.2} ...

Global site tag (gtag.js) - Google Analytics