不使用日期函式實現ADD_MONTHS函式功能(二)
看到開發區的nyfor版主出了一道題,用PL/SQL實現Oracle的ADD_MONTHS的功能,覺得比較有意思,忍不住嘗試了一下。
原文如下:http://www.itpub.net/thread-977079-1-1.html
不使用日期函式實現ADD_MONTHS函式功能:http://yangtingkun.itpub.net/post/468/460788
在原有的基礎上做了一點小改動。
由於這個東西比較耗費精力,因此自從上次的函式實現之後就沒有再花功夫去研究。
不過從其他人那裡學到了一個函式的用法,可以在不改變現有演算法的情況下,再次減少原始碼的長度:
SQL> CREATE OR REPLACE FUNCTION MY_ADD_MONTHS(P_DATE_STRING VARCHAR2, P_MONTHS NUMBER)
2 RETURN VARCHAR2 AS
3 SUBTYPE I IS INT;
4 N I:=P_DATE_STRING;
5 C I:=100;
6 D I:=N MOD C;
7 Y I:=N/C/C;
8 M I:=N/C MOD C;
9 Z I:=M+P_MONTHS;
10 FUNCTION F(Y I,M I) RETURN I
11 AS
12 BEGIN
13 RETURN 31-CASE WHEN M IN(4,6,9,11) THEN 1
14 WHEN M!=2 THEN 0
15 WHEN Y MOD 400 = 0 OR Y MOD 4 = 0 AND Y MOD C > 0 THEN 2
16 ELSE 3
17 END;
18 END;
19 BEGIN
20 N:=(Z MOD 12 + 11) MOD 12 + 1;
21 Z:=Y+(Z-N)/12;
22 IF D=F(Y,M) OR D>F(Z,N) THEN
23 D:=F(Z,N);
24 END IF;
25 RETURN Z*C*C+N*C+D;
26 END;
27 /
函式已建立。
SQL> SET SERVEROUT ON
SQL> declare
2 ln number;
3 ld date;
4 ls1 varchar2(8);
5 ls2 varchar2(8);
6 lt number := dbms_utility.get_time;
7 ex exception;
8 y number;
9 m number;
10 d number;
11 j number;
12 begin
13 for j in 0 .. 5000 loop
14 for y in 2000 .. 2001 loop
15 for m in 2 .. 4 loop
16 for d in 28 .. 31 loop
17 begin
18 ls1 := y || '0' || m || d;
19 begin
20 ld := to_date(ls1, 'yyyymmdd');
21 exception
22 when others then
23 exit;
24 end;
25 ld := add_months(ld, j);
26 ls2 := to_char(ld, 'yyyymmdd');
27 if nvl(my_add_months(ls1, j), '*') <> ls2 then
28 dbms_output.put_line('Sorry: stop at p_date_string=' || ls1 ||
29 ',p_months=' || j);
30 dbms_output.put_line('my_add_months returned: ' ||
31 my_add_months(ls1, j));
32 dbms_output.put_line('add_months returned: ' || ls2);
33 raise ex;
34 end if;
35
36 ls1 := to_char(add_months(ld, -j), 'yyyymmdd');
37 if nvl(my_add_months(ls2, -j), '*') <> ls1 then
38 dbms_output.put_line('Sorry: stop at p_date_string=' || ls2 ||
39 ',p_months=' || -j);
40 dbms_output.put_line('my_add_months returned: ' ||
41 my_add_months(ls2, -j));
42 dbms_output.put_line('add_months returned: ' || ls1);
43 raise ex;
44 end if;
45 exception
46 when ex then
47 raise;
48 when others then
49 raise;
50 end;
51 end loop;
52 end loop;
53 end loop;
54 end loop;
55 ln := 0;
56 for c in (select text
57 from user_source
58 where name = 'MY_ADD_MONTHS'
59 and type = 'FUNCTION') loop
60 ln := ln + nvl(lengthb(translate(c.text,
61 '*' || chr(9) || chr(10) || chr(13) ||
62 chr(32),
63 '*')),
64 0);
65 end loop;
66 lt := (dbms_utility.get_time - lt) / 100;
67 dbms_output.put_line('Congratulation ... Code Length: ' || ln ||
68 ' Bytes. Times: ' ||
69 to_char(to_date(to_char(lt, 'fm00000'), 'sssss'),
70 'hh24:mi:ss'));
71 exception
72 when ex then
73 null;
74 end;
75 /
Congratulation ... Code Length: 393 Bytes. Times: 00:00:03
PL/SQL 過程已成功完成。
在10g的PLSQL中,MOD(A,B)可以寫為A MOD B,利用這種方法將原始碼的最終程式碼縮短到了400之內。
不過如果再想縮短就必須修改演算法了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-327252/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 不使用日期函式實現ADD_MONTHS函式功能函式
- SQL函式之日期函式SQL函式
- 字元函式、數字函式和日期函式字元函式
- MySQL(四)日期函式 NULL函式 字串函式MySql函式Null字串
- 日期函式函式
- 【函式】Oracle函式系列(2)--數學函式及日期函式函式Oracle
- MYSQL事件使用 日期函式MySql事件函式
- 【Mysql 學習】日期函式函式MySql函式
- (函式)實現strstr函式函式
- MySQL函式大全(字串函式,數學函式,日期函式,系統級函式,聚合函式)MySql函式字串
- Oracle 函式大全(字串函式,數學函式,日期函式,邏輯運算函式,其他函式)Oracle函式字串
- ABAP日期函式函式
- Sybase日期函式函式
- sql 日期函式SQL函式
- SqlServer中使用CONVERT函式實現日期格式化SQLServer函式
- Oracle OCP(03):字元函式、數字函式和日期函式Oracle字元函式
- ORACLE單行函式與多行函式之四:日期函式示例Oracle函式
- [PY3]——函式——函式註解 | 實現型別檢查功能函式型別
- 利用指標實現strncmp函式功能指標函式
- 有關日期的SAP函式使用函式
- SQLSERVER日期函式(zt)SQLServer函式
- 日期時間函式函式
- 日期提取函式EXTRACT函式
- oracle日期函式(1)Oracle函式
- oracle日期函式(2)Oracle函式
- oracle日期函式(3)Oracle函式
- oracle日期函式(4)Oracle函式
- oracle日期函式(5)Oracle函式
- Oracle的日期函式Oracle函式
- Sql Server 日期函式SQLServer函式
- oracle 10g函式大全–日期型函式Oracle 10g函式
- oracle 10g函式大全--日期型函式Oracle 10g函式
- mysql 自定義分析函式 least 及 日期函式MySql函式AST
- 使用函式式實現觀察者模式模式函式模式
- 探索MySQL高階語句(數學函式、聚合函式、字串函式、日期時間函式)MySql函式字串
- 二分查詢(函式實現)函式
- C#函式實現的小功能集合C#函式
- SQL 10 函式 3 日期時間函式 - 5 計算日期差額SQL函式