工具 : 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
分享到:
相关推荐
- **C、函数不能递归调用**:错误,函数可以递归调用,只要不超过系统限制。 - **D、以上说法都不对**:错误,选项B正确。 **4. 有一产品表(编号,名称,价格,数量,所属分类),下列语法不正确的是?** - **...
在"第七章.doc"中,你可能会学习到关于PL/SQL的更高级主题,比如递归、游标的高级用法、存储过程的参数传递、复合类型以及PL/SQL与数据库并发控制的机制。每个实例都是精心设计的,旨在帮助你理解和掌握这些概念,...
§1.2.2 PL/SQL的好处主要体现在以下几个方面:1) 提高代码复用性,通过定义函数和过程,可以将常用操作封装起来;2) 提供更高级的数据控制,如循环、条件判断和异常处理;3) 提升性能,因为PL/SQL代码在服务器端...
SQL基本命令 PL/SQL使用的数据库操作语言还是基于SQL的,所以熟悉SQL是进行PL/SQL编程的基础。SQL语言的分类情况大致如下: 1) 数据定义语言(DDL):Create,Drop,Grant,Revoke,… 2) 数据操纵语言(DML):...
- **递归调用**:理解如何在过程或函数中使用递归调用来解决复杂问题。 3. **游标和集合** - **游标**:使用游标处理单行或多行结果集,以实现动态查询。 - **集合类型**:如VARRAY和NESTED TABLE,用于存储一组...
PL/SQL用于在Oracle数据库中创建存储过程、函数、触发器和包,提供高效且安全的数据处理。 2. **基本结构**:PL/SQL由声明部分(DECLARE)、执行部分(BEGIN...END)和异常处理部分(EXCEPTION)组成。声明部分定义...
你可以直接在SQL查询中使用PL/SQL函数,这使得数据库操作更加灵活。 触发器是另一种重要的PL/SQL元素,它是在特定数据库事件(如INSERT、UPDATE或DELETE)发生时自动执行的代码段。触发器可以用来实施复杂的业务...
2. **PL/SQL块**:包括匿名块、子程序(函数和过程)以及包的创建和调用。学习如何定义输入输出参数,理解作用域规则,以及如何在PL/SQL中使用SQL语句。 3. **游标**:用于处理单行或多行结果集,是PL/SQL中进行...
- 递归:通过在过程或函数内部调用自身实现递归操作。 3. 子程序: - 过程(PROCEDURE):无返回值的子程序,用于执行一系列操作。 - 函数(FUNCTION):返回一个特定值的子程序,可以被其他PL/SQL代码或SQL查询...
Oracle 递归函数是一种特殊的PL/SQL函数,可以用于解决复杂的树形结构查询问题。递归函数可以自我调用,以便遍历树形结构的每个节点,直到达到停止条件。 在 Oracle 中,递归函数的定义语法如下所示: ```sql ...
因此可以在将申明发送到甲骨文系统去执行之前使用PL/SQL区段和副程序来组合SQL申明,没有PL/SQL,甲骨文需要就每次处理SQL申明,在网络环境中,这将影响交通流量,而且增加响应时间。PL/SQL区段只被编译一次并且以可...
- 函数可以递归调用,但需谨慎处理避免无限循环。 4. **SQL查询语句**: - 选择题中的D选项是错误的,因为它试图在`GROUP BY`子句中使用聚合函数`MAX()`。 5. **触发器**: - 触发器可以在表上创建`INSTEAD OF`...
- 递归:可以使用自身调用来实现递归功能。 4. **PL/SQL块**: - 基本块:DECLARE-BEGIN-END结构,用于定义变量和执行语句。 - 动态块:EXECUTE IMMEDIATE语句用于动态执行SQL语句。 - 匿名块:未命名的PL/SQL...
4. PL/SQL基础:了解PL/SQL的语法结构,如声明变量、执行流程控制、处理异常,以及如何定义和调用存储过程和函数。 5. PL/SQL进阶:学习游标的使用,以及如何在PL/SQL中进行文件I/O和数据库连接操作。理解PL/SQL块...
9. **递归**:存储过程可以递归调用自身,但需要谨慎以避免无限循环。 10. **包(Package)**:包是将相关过程和函数组织在一起的结构,可以提高代码的模块化和重用性。包包含公共部分(可以被所有用户访问)和私有...
存储过程和函数是PL/SQL的核心部分,它们允许将一系列操作封装在一起,提高代码复用性和执行效率。通过实践脚本中的例子,你可以学习如何创建、调用和管理自定义的存储过程和函数。 5. **触发器** 触发器是在特定...
函数可以递归调用,但需要谨慎处理以避免无限循环(C错误)。 4. **SQL 查询**: - 选项D不正确,因为 `max()` 函数不能直接在 `WHERE` 子句中使用,而应在 `HAVING` 子句中使用。 5. **触发器**: - 可以在表上...