我需要将ISBN从10位转换为13位。我试过但没有得到正确的结果。这是我尝试过的代码,但没有给出正确的结果。
Create or replace FUNCTION F_ISBN_CONV_13 (ISBN_10 IN VARCHAR2) RETURN VARCHAR2
AS
V_ISBN_13 VARCHAR2(13);
BEGIN
SELECT
CASE WHEN LENGTH(ISBN_10) = 10 THEN
CASE WHEN SUBSTR(ISBN_10,1,3) = '801' THEN
'201' ||
SUBSTR(ISBN_10,1,9) ||
SUBSTR(
(
10 -
SUBSTR(
(
(
2 +
1 +
SUBSTR(ISBN_10,2,1) +
SUBSTR(ISBN_10,4,1) +
SUBSTR(ISBN_10,6,1) +
SUBSTR(ISBN_10,8,1)
) +
(
(
0 +
SUBSTR(ISBN_10,1,1) +
SUBSTR(ISBN_10,3,1) +
SUBSTR(ISBN_10,5,1) +
SUBSTR(ISBN_10,7,1) +
SUBSTR(ISBN_10,9,1)
)
) * 3
)
,-1
,1
)
)
,-1
,1
)
ELSE
'978' ||
SUBSTR(ISBN_10,1,9) ||
SUBSTR(
(
10-
SUBSTR(
(
(
9 +
8 +
SUBSTR(ISBN_10,2,1) +
SUBSTR(ISBN_10,4,1) +
SUBSTR(ISBN_10,6,1) +
SUBSTR(ISBN_10,8,1)
) +
(
(
7 +
SUBSTR(ISBN_10,1,1) +
SUBSTR(ISBN_10,3,1) +
SUBSTR(ISBN_10,5,1) +
SUBSTR(ISBN_10,7,1) +
SUBSTR(ISBN_10,9,1)
)
) * 3
)
,1
,1
)
)
,-1
,1
)
END
ELSE
ISBN_10
END INTO V_ISBN_13
FROM
DUAL;
RETURN V_ISBN_13;
EXCEPTION
--< code >
END F_ISBN_CONV_13;
答案 0 :(得分:1)
我认为以下代码应该是不言自明的。有关详细信息,请参阅维基百科链接。
-- https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_to_ISBN-13_conversion
create or replace function isbn10_to_13(p_isbn10 in varchar2)
return varchar2 is
v_isbn10_digits constant varchar2(9) := substr(replace(p_isbn10, '-', ''), 1, 9);
v_isbn13 varchar2(17) := '978-' || substr(p_isbn10, 1, length(p_isbn10) - 1);
v_checkdigit number;
begin
-- https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-13_check_digit_calculation
v_checkdigit :=
(1 * 9)
+ (3 * 7)
+ (1 * 8)
+ (3 * to_number(substr(v_isbn10_digits, 1, 1)))
+ (1 * to_number(substr(v_isbn10_digits, 2, 1)))
+ (3 * to_number(substr(v_isbn10_digits, 3, 1)))
+ (1 * to_number(substr(v_isbn10_digits, 4, 1)))
+ (3 * to_number(substr(v_isbn10_digits, 5, 1)))
+ (1 * to_number(substr(v_isbn10_digits, 6, 1)))
+ (3 * to_number(substr(v_isbn10_digits, 7, 1)))
+ (1 * to_number(substr(v_isbn10_digits, 8, 1)))
+ (3 * to_number(substr(v_isbn10_digits, 9, 1)))
;
v_checkdigit := 10 - mod(v_checkdigit, 10);
if v_checkdigit = 10
then
v_checkdigit := 0;
end if;
return v_isbn13 || v_checkdigit;
end;
/
示例强>
col isbn10 for a13
col isbn13 for a17
with isbn10(i10) as (
select '0-30-640615-x' from dual union all
select '0-07-223065-7' from dual union all
select '0-596-51446-x' from dual
)
select isbn10.i10 as isbn10, isbn10_to_13(isbn10.i10) as isbn13
from isbn10;
ISBN10 ISBN13
------------- -----------------
0-30-640615-x 978-0-30-640615-7
0-07-223065-7 978-0-07-223065-9
0-596-51446-x 978-0-596-51446-4
答案 1 :(得分:0)
我得到了正确的结果。
Create or replace FUNCTION F_ISBN_CONV_13 (ISBN_10 IN VARCHAR2) RETURN VARCHAR2
AS
V_ISBN_13 VARCHAR2(13);
BEGIN
SELECT
CASE WHEN LENGTH(ISBN_10) = 10 THEN
CASE WHEN SUBSTR(ISBN_10,1,3) = '801' THEN
'201' ||
SUBSTR(ISBN_10,1,9) ||
SUBSTR(
(
10 -
SUBSTR(
(
(
2 +
1 +
SUBSTR(ISBN_10,2,1) +
SUBSTR(ISBN_10,4,1) +
SUBSTR(ISBN_10,6,1) +
SUBSTR(ISBN_10,8,1)
) +
(
(
0 +
SUBSTR(ISBN_10,1,1) +
SUBSTR(ISBN_10,3,1) +
SUBSTR(ISBN_10,5,1) +
SUBSTR(ISBN_10,7,1) +
SUBSTR(ISBN_10,9,1)
)
) * 3
)
,-1
,1
)
)
,-1
,1
)
ELSE
'978' ||
SUBSTR(ISBN_10,1,9) ||
SUBSTR(
(
10-
SUBSTR(
(
(
9 +
8 +
SUBSTR(ISBN_10,2,1) +
SUBSTR(ISBN_10,4,1) +
SUBSTR(ISBN_10,6,1) +
SUBSTR(ISBN_10,8,1)
) +
(
(
7 +
SUBSTR(ISBN_10,1,1) +
SUBSTR(ISBN_10,3,1) +
SUBSTR(ISBN_10,5,1) +
SUBSTR(ISBN_10,7,1) +
SUBSTR(ISBN_10,9,1)
)
) * 3
)
,-1 -- Need to change here from '1' to '-1'
,1
)
)
,-1
,1
)
END
ELSE
ISBN_10
END INTO V_ISBN_13
FROM
DUAL;
RETURN V_ISBN_13;
EXCEPTION
--< code >
END F_ISBN_CONV_13;