oracle 函数的定义,oracle自定义函数

oracle自定义函数 (整理的几个可能平时会用到)

注:有些函数功能很简单,就是转换成Oracle的过程里面。。。

CREATE OR REPLACE Package  PKG_COMMON

IS

FUNCTION F_Str_Split (in_text IN VARCHAR2, in_delimiter IN

VARCHAR2) RETURN TYPE_STR;

FUNCTION F_Str_Have_Chinese(in_text IN VARCHAR2) RETURN

number;

FUNCTION F_Str_Have_Numeric(in_text IN VARCHAR2) RETURN

number;

FUNCTION F_Str_Have_English(in_text IN VARCHAR2) RETURN

number;

FUNCTION F_Str_Is_Numeric(in_text IN VARCHAR2) RETURN

number;

FUNCTION F_Str_Is_Date(in_text IN VARCHAR2) RETURN

number;

FUNCTION F_Str_Is_Phone(in_text IN VARCHAR2) RETURN

number;

FUNCTION F_Str_Is_Mail(in_text IN VARCHAR2) RETURN

number;

FUNCTION F_Str_Get_NongLi(i_SolarDay DATE) RETURN

VARCHAR2;

FUNCTION F_Str_Get_SubstrCount(in_text IN VARCHAR2,in_substr

IN VARCHAR2) RETURN  NUMBER;

FUNCTION F_Str_Get_SubstrValue(in_text IN

VARCHAR2,in_separator IN VARCHAR2,in_times1 IN NUMBER,in_times2 IN

NUMBER) RETURN  VARCHAR2;

FUNCTION F_Str_Get_GUID RETURN  VARCHAR2;

FUNCTION F_Str_Get_Prime(in_num IN NUMBER) RETURN

TYPE_INT;

FUNCTION F_Str_Order (in_text IN VARCHAR2,in_delimiter IN

VARCHAR2,in_order IN VARCHAR2) RETURN VARCHAR2;

End PKG_COMMON;

/

CREATE OR REPLACE Package body  PKG_COMMON

IS

FUNCTION F_Str_Split (in_text IN VARCHAR2, in_delimiter IN

VARCHAR2) RETURN TYPE_STR

IS

j INT := 0;

i INT := 1;

len INT := 0;

len1 INT := 0;

str VARCHAR2 (30000);

str_split TYPE_STR := TYPE_STR ();

BEGIN

len := LENGTH (in_text);

len1 := LENGTH (in_delimiter);

WHILE j < len

LOOP

j := INSTR (in_text,

in_delimiter, i);

IF j = 0

THEN

j := len;

str := SUBSTR (in_text, i);

str_split.EXTEND;

str_split (str_split.COUNT) := str;

IF i >= len

THEN

EXIT;

END IF;

ELSE

str := SUBSTR (in_text, i, j - i);

i := j + len1;

str_split.EXTEND;

str_split (str_split.COUNT) := str;

END IF;

END LOOP;

RETURN str_split;

END F_Str_Split;

FUNCTION F_Str_Have_Chinese(in_text IN VARCHAR2) RETURN

number

IS

BEGIN

IF LENGTH(in_text)=LENGTHB(in_text) THEN

RETURN

1;

ELSE

RETURN

0;

END IF;

END F_Str_Have_Chinese;

FUNCTION F_Str_Have_Numeric(in_text IN VARCHAR2) RETURN

number

IS

l_num number;

BEGIN

SELECT REGEXP_INSTR (in_text,'[0-9]+')

INTO l_num FROM DUAL;

IF l_num=0 THEN

RETURN

1;

ELSE

RETURN

0;

END IF;

END F_Str_Have_Numeric;

FUNCTION F_Str_Have_English(in_text IN VARCHAR2) RETURN

number

IS

l_num number;

BEGIN

SELECT REGEXP_INSTR (lower(in_text),'[a-z]+')

INTO l_num FROM DUAL;

IF l_num=0 THEN

RETURN

1;

ELSE

RETURN

0;

END IF;

END F_Str_Have_English;

FUNCTION F_Str_Is_Numeric(in_text IN VARCHAR2) RETURN

number

IS

l_str varchar2(10);

BEGIN

BEGIN

SELECT  *

INTO l_str FROM dual where regexp_like(in_text, '^[0123456789]+$');

RETURN 0;

EXCEPTION

WHEN NO_DATA_FOUND THEN

RETURN 1;

END;

END F_Str_Is_Numeric;

FUNCTION F_Str_Is_Date(in_text IN VARCHAR2) RETURN

number

IS

val DATE;

BEGIN

val := TO_DATE(NVL(in_text, 'a'), 'yyyy-mm-dd

hh24:mi:ss');

RETURN 0;

EXCEPTION

WHEN OTHERS THEN

RETURN 1;

END  F_Str_Is_Date;

FUNCTION F_Str_Is_Phone(in_text IN VARCHAR2) RETURN

number

IS

l_begin varchar2(1);

l_str varchar2(2);

l_length number;

l_number number;

BEGIN

l_number:=F_Str_Is_Numeric(in_text);

l_begin:=substr(in_text,1,1);

l_length:=length(in_text);

IF l_number =0 THEN

IF l_begin

=1  THEN  --1开头的数字可能是手机号码

IF LENGTH(in_text)=11 THEN  --长度为11位,继续判断

BEGIN

SELECT  *

INTO l_str FROM dual where

REGEXP_LIKE(in_text,'^(134|135|136|137|138|139|147|150|151|152|157|158|159|182|187|188)')

;

RETURN 4;

EXCEPTION

WHEN NO_DATA_FOUND THEN

BEGIN

SELECT  * INTO l_str FROM dual

where REGEXP_LIKE(in_text,'^(130|131|132|155|156|185|186)') ;

RETURN 5;

EXCEPTION

WHEN NO_DATA_FOUND THEN

BEGIN

SELECT  *

INTO l_str FROM dual where REGEXP_LIKE(in_text,'^(133|180|189)')

;

RETURN 6;

EXCEPTION

WHEN

NO_DATA_FOUND THEN

RETURN 2;

END;

END;

END;

ELSE --长度没有11位,非法手机号码

RETURN 2;

END IF;

ELSIF

l_begin<>1 AND (l_length=7 OR l_length=8 OR l_length=11 OR

l_length=12) THEN--可能是固定电话

RETURN 7;

ELSE

RETURN 3;

END

IF;

ELSE  --含有非数字

RETURN

1;

END IF;

END F_Str_Is_Phone;

FUNCTION F_Str_Is_Mail(in_text IN VARCHAR2) RETURN

number

IS

l_str varchar2(10);

BEGIN

BEGIN

SELECT  *

INTO l_str FROM dual where

REGEXP_LIKE(in_text,'^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$');

RETURN 0;

EXCEPTION

WHEN NO_DATA_FOUND THEN

RETURN 1;

END;

EXCEPTION

WHEN OTHERS THEN

RETURN 1;

END  F_Str_Is_Mail;

FUNCTION F_Str_Get_NongLi(i_SolarDay DATE) RETURN

VARCHAR2

AS

v_OffSet  INT;

v_Lunar  INT;

--

农历年是否含闰月,几月是闰月,闰月天数,其它月天数

v_YearDays  INT;  --

农历年所含天数

v_MonthDays  INT;  --

农历月所含天数

v_LeapMonthDays  INT;  -- 农历闰月所含天数

v_LeapMonth  INT;  -- 农历年闰哪个月

1-12 , 没闰传回 0

v_LeapFlag  INT;  --

某农历月是否为闰月  1:是  0:不是

v_MonthNo  INT;  -- 某农历月所对应的2进制数 如农历3月:

001000000000

i  INT;

j  INT;

k  INT;

v_Year  INT;

-- i_SolarDay 对应的农历年

v_Month  INT;

-- i_SolarDay 对应的农历月

v_Day  INT;

-- i_SolarDay 对应的农历日

v_temp  VARCHAR2(25);

o_OutputDate  VARCHAR2(25); -- 返回值  格式:农历 ****年 **(闰)月 **日

e_ErrMsg  VARCHAR2(200);

e_ErrDate  EXCEPTION;

BEGIN

--输入参数判断

IF i_SolarDay=TO_DATE('2050-01-23','YYYY-MM-DD')

THEN

RAISE

e_ErrDate;

END IF ;

-- i_SolarDay 到 1900-01-30(即农历1900-01-01的前一天)

的天数

v_OffSet := TRUNC(i_SolarDay, 'DD') -

TO_DATE('1900-01-30', 'YYYY-MM-DD');

-- 确定农历年开始

i := 1900;

WHILE i < 2050 AND v_OffSet > 0 LOOP

v_YearDays

:= 348;  --

29*12 以每年12个农历月,每个农历月含29个农历日为基数

v_LeapMonthDays := 0;

--

取出农历年是否含闰月,几月是闰月,闰月天数,其它月天数

--

如农历2001年: 0x0d954(16进制) -> 55636(10进制) -> 0 110110010101

0100(2进制)

--

1,2,4,5,8,10,12月大, 3,6,7,9,11月小, 4月为闰月,闰月小

SELECT

Data10 INTO v_Lunar FROM T_BASE_SolarData WHERE YearId = i;

--

传回农历年的总天数

j :=

32768;

--

依次判断v_Lunar年个月是否为大月,是则加一天

WHILE j

> 8 LOOP  -- 闰月另行判断 8 -> 0 000000000000 1000

IF BITAND(v_Lunar, j) + 0

> 0 then

v_YearDays := v_YearDays +

1;

END IF;

j := j/2;  -- 判断下一个月是否为大

END

LOOP;

--

传回农历年闰哪个月 1-12 , 没闰传回 0  15 -> 1 0000

v_LeapMonth := BITAND(v_Lunar, 15) + 0;

--

传回农历年闰月的天数 ,加在年的总天数上

IF

v_LeapMonth > 0 THEN

-- 判断闰月大小 65536 -> 1

000000000000 0000

IF BITAND(v_Lunar, 65536)+0

> 0 THEN

v_LeapMonthDays := 30;

ELSE

v_LeapMonthDays := 29;

END IF;

v_YearDays := v_YearDays +

v_LeapMonthDays;

END

IF;

v_OffSet

:= v_OffSet - v_YearDays;

i := i +

1;

END LOOP;

IF v_OffSet <= 0 THEN

--

i_SolarDay 在所属农历年(即i年)中的第 v_OffSet 天

v_OffSet

:= v_OffSet + v_YearDays;

i := i -

1;

END IF;

-- 确定农历年结束

v_Year := i;

-- 确定农历月开始

i := 1;

SELECT Data10 INTO v_Lunar FROM T_BASE_SolarData

WHERE YearId = v_Year;

-- 判断那个月是润月

-- 如农历2001年 (55636,15 -> 0 1101100101010100,

1111 -> 4) 即润4月,且闰月小

v_LeapMonth := BITAND(v_Lunar, 15) +

0;

v_LeapFlag := 0;

WHILE i < 13 AND v_OffSet > 0

LOOP

--

判断是否为闰月

v_MonthDays := 0;

IF

(v_LeapMonth > 0 AND i = (v_LeapMonth + 1) AND v_LeapFlag = 0)

THEN

-- 是闰月

i := i - 1;

k := i;  -- 保存是闰月的时i的值

v_LeapFlag := 1;

-- 传回农历年闰月的天数

IF BITAND(v_Lunar, 65536)+0

> 0 THEN

v_MonthDays := 30;

ELSE

v_MonthDays := 29;

END IF;

ELSE

-- 不是闰月

j := 1;

v_MonthNo := 65536;

-- 计算 i 月对应的2进制数 如农历3月:

001000000000

WHILE j<= i LOOP

v_MonthNo :=

v_MonthNo/2;

j := j + 1;

END LOOP;

-- 计算农历 v_Year 年 i 月的天数

IF BITAND(v_Lunar,

v_MonthNo)+0 > 0 THEN

v_MonthDays := 30;

ELSE

v_MonthDays := 29;

END IF;

END

IF;

--

解除闰月

IF

v_LeapFlag = 1 AND i = v_LeapMonth +1 THEN

v_LeapFlag := 0;

END

IF;

v_OffSet

:= v_OffSet - v_MonthDays;

i := i +

1;

END LOOP;

IF v_OffSet <= 0 THEN

--

i_SolarDay 在所属农历月(即i月)中的第 v_OffSet 天

v_OffSet

:= v_OffSet + v_MonthDays;

i := i -

1;

END IF;

-- 确定农历月结束

v_Month := i;

-- 确定农历日结束

v_Day := v_OffSet;

-- 格式化返回值

o_OutputDate := TO_CHAR(v_Year)||'年';

IF k = i THEN

o_OutputDate := o_OutputDate || LPAD(TO_CHAR(v_Month), 2,

'0');

ELSE

o_OutputDate := o_OutputDate || LPAD(TO_CHAR(v_Month), 2,

'0');

END IF;

o_OutputDate := o_OutputDate||'月' ||

LPAD(TO_CHAR(v_Day), 2, '0');

RETURN o_OutputDate;

EXCEPTION

WHEN e_Errdate THEN

RETURN '日期错误! 有效范围(阳历):

1900/01/31 - 2050/01/22';

WHEN OTHERS THEN

e_ErrMsg

:=SUBSTR(SQLERRM,1,200);

RETURN e_ErrMsg;

END;

FUNCTION F_Str_Get_SubstrCount(in_text IN VARCHAR2,in_substr

IN VARCHAR2) RETURN  NUMBER

IS

l_count  number :=0;

BEGIN

SELECT LENGTH(REGEXP_REPLACE(REPLACE(in_text,

in_substr, '@'),  '[^@]+',  ''))

COUNT INTO l_count FROM DUAL;

IF l_count IS NULL THEN

RETURN 0;

ELSE

RETURN l_count;

END IF;

EXCEPTION

WHEN

NO_DATA_FOUND THEN

RETURN 0;

END F_Str_Get_SubstrCount;

FUNCTION F_Str_Get_SubstrValue(in_text IN

VARCHAR2,in_separator IN VARCHAR2,in_times1 IN NUMBER,in_times2 IN

NUMBER) RETURN  VARCHAR2

IS

l_total  number;

l_begin  number;

l_end  number;

BEGIN

l_total:=F_Str_Get_SubstrCount(in_text,in_separator);

IF in_times1<=0 THEN

l_begin:=0;

ELSE

SELECT

INSTR(in_text,in_separator,1,in_times1)+1 INTO l_begin FROM

DUAL;

END IF;

IF in_times2>l_total THEN

l_end:=LENGTH(in_text);

ELSE

SELECT

INSTR(in_text,in_separator,1,in_times2) INTO l_end FROM DUAL;

END IF;

RETURN

SUBSTR(in_text,l_begin,(l_end-l_begin));

END F_Str_Get_SubstrValue;

FUNCTION F_Str_Get_GUID RETURN  VARCHAR2

IS

l_guid  varchar2(40);

BEGIN

select sys_guid() into l_guid from dual;

return l_guid;

END F_Str_Get_GUID;

FUNCTION F_Str_Get_Prime(in_num IN NUMBER) RETURN

TYPE_INT

IS

my_arr_prime TYPE_INT:=TYPE_INT();

n_cur_mult number(10):=1;

n_prime_1 number(10):=1;

n_prime_2 number(10):=2;

n_max number(10):=

floor((in_num+1)/6);

n_arr_ind number(10):=1;

b_prime number(1):=0;

n_arr_max number(10):=2;

begin

my_arr_prime.EXTEND;

my_arr_prime(1):=2;

my_arr_prime.EXTEND;

my_arr_prime(2):=3;

for i in 1..n_max

loop

n_prime_1 := i*6-1;

n_prime_2 := i*6+1;

n_cur_mult := ceil(sqrt(n_prime_2));

for j

in 1..2 loop

if j =2 then

n_prime_1:= n_prime_2;

end if;

if n_prime_1 > in_num

then

exit;

end if;

n_arr_ind:=1;

b_prime :=0;

while n_arr_ind <=

n_arr_max and my_arr_prime(n_arr_ind)<= n_cur_mult loop

if

mod(n_prime_1, my_arr_prime(n_arr_ind)) =0 then

b_prime :=1;

exit;

end

if;

n_arr_ind

:= n_arr_ind+1;

end loop;

if b_prime = 0 then

n_arr_max := n_arr_max+1;

my_arr_prime.EXTEND;

my_arr_prime(n_arr_max) := n_prime_1;

end if;

end

loop;

end loop;

RETURN

my_arr_prime;

END  F_Str_Get_Prime;

FUNCTION F_Str_Order (in_text IN VARCHAR2,in_delimiter IN

VARCHAR2,in_order IN VARCHAR2) RETURN VARCHAR2

IS

l_result varchar2(4000);

BEGIN

IF in_order='0' THEN

SELECT

WMSYS.WM_CONCAT(id) INTO l_result

FROM

(

SELECT substr(a, (instr(a,

in_delimiter, 1,LEVEL) + 1),  (instr(a,

in_delimiter, 1,LEVEL+1) - (instr(a, in_delimiter, 1,LEVEL) + 1)) )

id

FROM

(

SELECT in_delimiter||in_text||in_delimiter AS a

FROM DUAL

)  CONNECT

BY  LEVEL <= (length(a) -

nvl(length(REPLACE(a, in_delimiter, '')), 0) -1)

ORDER BY to_number(ID)

ASC

);

ELSE

SELECT

WMSYS.WM_CONCAT(id) INTO l_result

FROM

(

SELECT substr(a, (instr(a,

in_delimiter, 1,LEVEL) + 1),  (instr(a,

in_delimiter, 1,LEVEL+1) - (instr(a, in_delimiter, 1,LEVEL) + 1)) )

id

FROM

(

SELECT in_delimiter||in_text||in_delimiter AS a

FROM DUAL

)  CONNECT

BY  LEVEL <= (length(a) -

nvl(length(REPLACE(a, in_delimiter, '')), 0) -1)

ORDER BY to_number(ID)

DESC

);

END IF;

RETURN l_result;

END F_Str_Order;

End PKG_COMMON;

/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值