15位身份证升18位身份证的Oracle函数[sql]www.2cto.comCREATEORREPLACEFUNCTIONFUNC_AAC00215_18(prm_aac002varchar2)returnvarchar2isll_inumber(4):18;ll_row...
[sql] www.2cto.com
CREATE OR REPLACE FUNCTION FUNC_AAC00215_18 (prm_aac002 varchar2)
return varchar2 is
ll_i number(4) := 18;
ll_row number(5) := 0;
var_aac002 varchar2(18);
ll_sfz18 number(3);
ll_sfz varchar2(3);
var_sfz18 varchar(18);
var_date varchar(10);
dat_date date;
ll_num number(2);
s_sfz varchar2(15);
s_sss varchar2(20):='X';
v_newaac002 varchar(18);
n_length number(2);
V_CHAR varchar2(15);
s_date varchar2(15);
begin
if prm_aac002 is null then
return '';
end if;
if length(prm_aac002) <> 15 and length(prm_aac002) <> 18 then
return &#39;&#39;;
end if;
if length(prm_aac002) = 18 then
n_length := length(prm_aac002);
FOR n_i IN 1 .. n_length LOOP
V_CHAR := SUBSTR(prm_aac002, n_i, 1);
IF V_CHAR IN (&#39;0&#39;, &#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;7&#39;, &#39;8&#39;, &#39;9&#39;) AND N_I<18 THEN
v_newaac002 :=prm_aac002;
ELSIF N_I=18 AND V_CHAR IN(&#39;0&#39;, &#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;7&#39;, &#39;8&#39;, &#39;9&#39;,&#39;X&#39;) THEN
v_newaac002 :=prm_aac002;
else
return &#39;含义非法字符!&#39;;
END IF;
END LOOP;
/*2. 取出生日期是否有效*/
s_date := substr(prm_aac002, 7, 8);
begin
select to_date(s_date, &#39;yyyymmdd&#39;) into dat_date from dual;
exception
when others then
return &#39;出生日期不对!&#39;;
end;
if substr(prm_aac002,7, 2)>20 or substr(prm_aac002,7, 2) <19 then
return &#39;年度不对!&#39;;
end if;
/*3. 最后位效验*/
while n_length >= 2 loop
begin
select to_number(substr(prm_aac002, 19 - n_length, 1))
into ll_num
from dual;
exception
when others then
return &#39;&#39;;
end;
ll_row := ll_row + mod(power(2, (n_length - 1)), 11) *
to_number(substr(prm_aac002, 19 - n_length, 1));
n_length := n_length - 1;
end loop;
ll_sfz18 := mod(ll_row, 11);
select decode(to_char(ll_sfz18),&#39;0&#39;,&#39;1&#39;,&#39;1&#39;,&#39;0&#39;,&#39;2&#39;,&#39;X&#39;,&#39;3&#39;,&#39;9&#39;,&#39;4&#39;,&#39;8&#39;,&#39;5&#39;,&#39;7&#39;,&#39;6&#39;,&#39;6&#39;,&#39;7&#39;,&#39;5&#39;,&#39;8&#39;,&#39;4&#39;,&#39;9&#39;,&#39;3&#39;,&#39;10&#39;,&#39;2&#39;)
into ll_sfz
from dual;
if ll_sfz <> substr(prm_aac002,18, 1) then
return &#39;尾数不对!应为&#39;||ll_sfz;
end if;
RETURN v_newaac002;
end if;
if prm_aac002 = &#39;111111111111111111&#39; then
return &#39;&#39;;
end if;
if s_sfz <>&#39;X&#39; then
s_sss := s_sfz;
else
s_sss := prm_aac002;
end if;
if length(prm_aac002)=15 then
var_date := &#39;19&#39; || substr(s_sss, 7, 6);
begin
select to_date(var_date, &#39;yyyymmdd&#39;) into dat_date from dual;
exception
when others then
return &#39;&#39;;
end;
var_aac002 := substr(s_sss, 0, 6) || &#39;19&#39; ||
substr(s_sss, 7, 9);
while ll_i >= 2 loop
begin
select to_number(substr(var_aac002, 19 - ll_i, 1))
into ll_num
from dual;
exception
when others then
return &#39;&#39;;
end;
ll_row := ll_row + mod(power(2, (ll_i - 1)), 11) *
to_number(substr(var_aac002, 19 - ll_i, 1));
ll_i := ll_i - 1;
end loop;
ll_sfz18 := mod(ll_row, 11);
select decode(to_char(ll_sfz18),&#39;0&#39;,&#39;1&#39;,&#39;1&#39;,&#39;0&#39;,&#39;2&#39;,&#39;X&#39;,&#39;3&#39;,&#39;9&#39;,&#39;4&#39;,&#39;8&#39;,&#39;5&#39;,&#39;7&#39;,&#39;6&#39;,&#39;6&#39;,&#39;7&#39;,&#39;5&#39;,&#39;8&#39;,&#39;4&#39;,&#39;9&#39;,&#39;3&#39;,&#39;10&#39;,&#39;2&#39;)
into ll_sfz
from dual;
var_sfz18 := var_aac002 || ll_sfz;
return var_sfz18;
end if;
end func_aac00215_18;
/
show errors;
使用如下:
[sql]
SELECT func_aac00215_18(&#39;371102841104258&#39;) FROM dual;