17,377
社区成员
发帖
与我相关
我的任务
分享
CREATE FUNCTION Barcode_CheckSum(IN my_barcode CHAR(12))
RETURNS INTEGER
RETURN
( SELECT ABS(SUM(CAST ( SUBSTRING( barcode Weights.seq FOR 1) AS INTEGER) * Weights.wgt))
FROM ( VALUES (CAST( 1 AS INTEGER), CAST( -1 AS INTEGER)),
( 2, +1),( 3, -1),( 4, +1),( 5, -1),( 6, +1),( 7, -1),( 8, +1),( 9, -1),( 10, +1),( 11, -1),( 12, +1)) AS Weights(seq, wgt)
WHERE barcode NOT SIMILAR TO '%^[0-9]%');
CREATE OR REPLACE FUNCTION Barcode_CheckSum( my_barcode IN VARCHAR)
RETURN INTEGER
AS
num NUMBER:=0;
BEGIN
BEGIN
SELECT MOD(ABS(SUM( SUBSTR( my_barcode, Weights.seq, 1) * Weights.wgt)),10)
INTO num
FROM ( SELECT LEVEL seq,Power(-1,level) wgt
FROM dual
CONNECT BY LEVEL<=12)
Weights
WHERE NOT REGEXP_LIKE(my_barcode, '[^[:digit:]]');
END;
RETURN num;
END;
CREATE OR REPLACE FUNCTION Barcode_CheckSum( my_barcode IN VARCHAR)
RETURN INTEGER
AS
num NUMBER:=0;
BEGIN
BEGIN
SELECT ABS(SUM( SUBSTR( my_barcode, Weights.seq, 1) * Weights.wgt))
INTO num
FROM ( SELECT LEVEL seq,Power(-1,level) wgt
FROM dual
CONNECT BY LEVEL<=12)
Weights
WHERE NOT REGEXP_LIKE(my_barcode, '[^[:digit:]]');
END;
RETURN num;
END;
SQL> ed
已写入 file afiedt.buf
1 create or replace function fun_dt(str varchar2) return number
2 as
3 sum1 number:=0;
4 sum2 number:=0;
5 s1 varchar2(10);
6 s2 varchar2(10);
7 num varchar2(100);
8 begin
9 select decode(sign(length(str)-length(regexp_replace(str,'[[:alpha:]]',''))),0,str,null)
10 into num from dual;
11 if num is null or length(num)<12 then
12 return null;
13 else
14 for i in 1..length(num) loop
15 if mod(i,2)=0 then
16 select substr(num,i,1) into s1 from dual;
17 sum1:=sum1+s1;
18 else
19 select substr(num,i,1) into s2 from dual;
20 sum2:=sum2+s2;
21 end if;
22 end loop;
23 return abs(mod((sum1-sum2),10)) ;
24 end if;
25 exception
26 when others then
27 dbms_output.put_line(sqlcode||' '||sqlerrm);
28* end;
SQL> /
函数已创建。
SQL> select fun_dt('123456789012') f1,
2 fun_dt('12s3456789012') f2,
3 fun_dt('12233') f3,
4 fun_dt('111111111111') f2
5 from dual
6 /
F1 F2 F3 F2
---------- ---------- ---------- ----------
4 0
CREATE OR REPLACE FUNCTION func_identify_barcode(i_str VARCHAR2)
RETURN VARCHAR2 AS
v_sign NUMBER;
v_result NUMBER;
BEGIN
-- exp:i_str 为: abc1
-- 连接后的字符串:'0123456789abc1', 比'0123456789' 要长,
-- 在'0123456789abc1'而不在0123456789中的字符,由于没有替代的字符,
-- abc将要从 i_str(abc1)中删去,只剩下1,所以经过translate函数处理后返回1,其长度也为:1。
IF length(i_str) != length(translate(i_str, '0123456789' || i_str, '0123456789'))
OR length(i_str) != 12 THEN
--{
RETURN NULL;
--}
END IF;
v_sign := 1;
v_result := 0;
FOR i IN 1 .. length(i_str) LOOP
--{
v_sign := -v_sign;
v_result := v_result + substr(i_str, i, 1) * v_sign;
--}
END LOOP;
RETURN abs(mod(v_result,10));
END;
/
--SELECT func_identify_barcode('92949a789012') result from dual;
CREATE OR REPLACE FUNCTION Barcode_CheckSum( my_barcode IN VARCHAR)
RETURN INTEGER
AS
num NUMBER:=0;
BEGIN
BEGIN
SELECT ABS(MOD(SUM( SUBSTR( my_barcode, Weights.seq, 1) * Weights.wgt),10))
INTO num
FROM ( SELECT LEVEL seq,Power(-1,level-1) wgt
FROM dual
CONNECT BY LEVEL<13)
Weights
WHERE NOT REGEXP_LIKE(my_barcode, '[^[:digit:]]');
END;
RETURN num;
END;
-- select Barcode_CheckSum('121212121212') from daul;
CREATE FUNCTION Barcode_CheckSum(IN my_barcode CHAR(12))
RETURNS INTEGER
RETURN
( SELECT ABS(SUM(CAST ( SUBSTRING( barcode FROM Weights.seq FOR 1) AS INTEGER) * Weights.wgt))
FROM ( VALUES (CAST( 1 AS INTEGER), CAST( -1 AS INTEGER)),
( 2, +1),( 3, -1),( 4, +1),( 5, -1),( 6, +1),( 7, -1),( 8, +1),( 9, -1),( 10, +1),( 11, -1),( 12, +1)) AS Weights(seq, wgt)
WHERE barcode NOT SIMILAR TO '%[^0-9]%');
SQL> SELECT id
2 FROM a
3 WHERE
4 NOT REGEXP_LIKE(a.id,'%^[0-9]%')
5 ;
ID
----------------------------------------------------------------
036AFCLASLAMOMYR
036AFCLASLAMONOK
CREATE FUNCTION Barcode_CheckSum(IN my_barcode CHAR(12))
RETURNS INTEGER
RETURN
( SELECT ABS(SUM(CAST ( SUBSTRING( barcode FROM Weights.seq FOR 1) AS INTEGER) * Weights.wgt))
FROM ( VALUES (CAST( 1 AS INTEGER), CAST( -1 AS INTEGER)),
( 2, +1),( 3, -1),( 4, +1),( 5, -1),( 6, +1),( 7, -1),( 8, +1),( 9, -1),( 10, +1),( 11, -1),( 12, +1)) AS Weights(seq, wgt)
WHERE barcode NOT SIMILAR TO '%^[0-9]%');
--写那么多union all
--还不如这样直接点
SELECT LEVEL seq,Power(-1,level) wgt
FROM dual
CONNECT BY LEVEL<=12
SQL> CREATE OR REPLACE FUNCTION Barcode_CheckSum( my_barcode IN VARCHAR)
2 RETURN INTEGER
3 AS
4
5 num NUMBER:=0;
6 BEGIN
7 BEGIN
8 SELECT ABS(SUM( SUBSTR( my_barcode, Weights.seq, 1) * Weights.wgt))
9 INTO num
10 FROM (SELECT 1 seq, 1 wgt FROM dual
11 UNION ALL
12 SELECT 2 , -1 FROM dual
13 UNION ALL
14 SELECT 3 , 1 FROM dual
15 UNION ALL
16 SELECT 4 , -1 FROM dual
17 UNION ALL
18 SELECT 5 , 1 FROM dual
19 UNION ALL
20 SELECT 6 , -1 FROM dual
21 UNION ALL
22 SELECT 7 , 1 FROM dual
23 UNION ALL
24 SELECT 8 , -1 FROM dual
25 UNION ALL
26 SELECT 9 , 1 FROM dual
27 UNION ALL
28 SELECT 10 , -1 FROM dual
29 UNION ALL
30 SELECT 11 , 1 FROM dual
31 UNION ALL
32 SELECT 12 , -1 FROM dual)
33 Weights
34 WHERE NOT REGEXP_LIKE(my_barcode, '[^[:digit:]]');
35
36 END;
37
38 RETURN num;
39 END;
40 /
Function created
SQL>
SQL> select Barcode_CheckSum('111111111111') from dual;
BARCODE_CHECKSUM('111111111111
------------------------------
0
SELECT ABS(SUM( SUBSTR( '121212121212', Weights.seq, 1) * Weights.wgt))
FROM (SELECT 1 seq, 1 wgt FROM dual
UNION ALL
SELECT 2 , -1 FROM dual
UNION ALL
SELECT 3 , 1 FROM dual
UNION ALL
SELECT 4 , -1 FROM dual
UNION ALL
SELECT 5 , 1 FROM dual
UNION ALL
SELECT 6 , -1 FROM dual
UNION ALL
SELECT 7 , 1 FROM dual
UNION ALL
SELECT 8 , -1 FROM dual
UNION ALL
SELECT 9 , 1 FROM dual
UNION ALL
SELECT 10 , -1 FROM dual
UNION ALL
SELECT 11 , 1 FROM dual
UNION ALL
SELECT 12 , -1 FROM dual)
Weights
WHERE NOT REGEXP_LIKE('121212121212', '[^[:digit:]]');
CREATE OR REPLACE FUNCTION Barcode_CheckSum( my_barcode IN VARCHAR)
RETURN INTEGER
AS
BEGIN
RETURN SELECT ABS(SUM( SUBSTR( '121212121212', Weights.seq, 1) * Weights.wgt))
FROM (SELECT 1 seq, 1 wgt FROM dual
UNION ALL
SELECT 2 , -1 FROM dual
UNION ALL
SELECT 3 , 1 FROM dual
UNION ALL
SELECT 4 , -1 FROM dual
UNION ALL
SELECT 5 , 1 FROM dual
UNION ALL
SELECT 6 , -1 FROM dual
UNION ALL
SELECT 7 , 1 FROM dual
UNION ALL
SELECT 8 , -1 FROM dual
UNION ALL
SELECT 9 , 1 FROM dual
UNION ALL
SELECT 10 , -1 FROM dual
UNION ALL
SELECT 11 , 1 FROM dual
UNION ALL
SELECT 12 , -1 FROM dual)
Weights
WHERE NOT REGEXP_LIKE('121212121212', '[^[:digit:]]')
AND ROWNUM<2;
END;
LINE/COL ERROR
-------- ---------------------------------------------------------------------5/10 PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + ; case mod new not null <an identifier>
CREATE OR REPLACE FUNCTION BarcodeCheckSum( my_barcode IN VARCHAR)
RETURN INTEGER AS
v_my_barcode VARCHAR(12):= NULL;
barcode_checkers INTEGER:=0;
idx INTEGER :=1;
sgn INTEGER:=-1;
num_flg NUMBER:=NULL;
BEGIN
-- 这个begin块可以不用,只是为了便于维护,才加了一个v_my_barcode 变量,
-- 如果 my_barcode 的名字需要修改时,只用改一处即可
BEGIN
--{
v_my_barcode := trim(my_barcode);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('my_barcode too long');
RETURN -1;
--}
END;
---- check length
IF length(v_my_barcode) <>12 THEN
--{
RETURN -1;
dbms_output.put_line('my_barcode length is not right');
--}
END IF;
----check all char is numchar exception point
-- 利用 to_number判断是不是全部是数字字符,
-- 但单用to_number不能排除有小数点的情况,
-- 所以用like排除一下
-- 如果有小数点,num_flg就不为空, 再在下一个if块中判断
-- 值得一提的时,虽然others可以捕获所有异常,但是如果一个异常被前一个when捕获,
-- when other 就不会再进行捕获
BEGIN
--{
SELECT to_number(v_my_barcode)
INTO num_flg
FROM dual WHERE v_my_barcode LIKE '%.%';
EXCEPTION
WHEN no_data_found THEN
num_flg := NULL;
WHEN OTHERS THEN
dbms_output.put_line('my_barcode there are some NAN');
dbms_output.put_line(SQLCODE||' '|| SQLERRM);
RETURN -2;
--}
END;
--check all char is numchar, exception point
IF num_flg IS NOT NULL THEN
--{
dbms_output.put_line('my_barcode there have one point');
RETURN -2;
--}
END if;
--计算各奇数位的和减去各偶数位的和
WHILE idx <13 LOOP
--{
sgn := -sgn;
barcode_checkers := barcode_checkers + to_number(substr(v_my_barcode,idx,1))*sgn;
idx := idx + 1;
--}
END LOOP;
--
RETURN ABS(MOD(barcode_checkers,10));
END BarcodeCheckSum;
/
select BarcodeCheckSum('111111114111') AS barcode from dual;