Validate VIN (Vehicle Identification Number) using Decode/Mod Function
Rajnikant Tahlyan, February 13, 2007 - 4:15 pm UTC
CREATE OR REPLACE FUNCTION VALIDATE_VIN(IN_VIN IN VARCHAR2) RETURN NUMBER AS
--Author: Rajnikant Tahlyan
--Date: 13-Feb-2007
--MEANING OF DIFFERENT CHARACTERS IN A VIN
--CHARACTER 1 --> COUNTRY
--CHARACTER 2 --> MANUFACTURER
--CHARACTER 3 --> MAKE
--CHARACTER 4-6 --> ENGINE
--CHARACTER 7 --> BODY/TRANSMISSION
--CHARACTER 8 --> TRIM LEVEL/RESTRAINT
--CHARACTER 9 --> CHECK DIGIT
--CHARACTER 10 --> MODEL YEAR
--CHARACTER 11 --> ASSEMBLY PLANT
--CHARACTER 12-17 --> SERIAL NUMBER
V_CHECK_DIGIT_NUM NUMBER;
V_CHECK_DIGIT VARCHAR2(1);
--VALUES ASSIGNED TO CHARACTERS AS PER "SUPPLEMENT TO TRUCK BLUE BOOK - 1999 TRUCK IDENTIFICATION"
V_A NUMBER := 1;
V_B NUMBER := 2;
V_C NUMBER := 3;
V_D NUMBER := 4;
V_E NUMBER := 5;
V_F NUMBER := 6;
V_G NUMBER := 7;
V_H NUMBER := 8;
V_J NUMBER := 1;
V_K NUMBER := 2;
V_L NUMBER := 3;
V_M NUMBER := 4;
V_N NUMBER := 5;
V_P NUMBER := 7;
V_R NUMBER := 9;
V_S NUMBER := 2;
V_T NUMBER := 3;
V_U NUMBER := 4;
V_V NUMBER := 5;
V_W NUMBER := 6;
V_X NUMBER := 7;
V_Y NUMBER := 8;
V_Z NUMBER := 9;
BEGIN
IF (LENGTH(IN_VIN) <> 17) THEN
RETURN 1; --FAILURE --> ERRORNEOUS VIN, AFTER 1981 EACH VIN HAS TO BE OF 17 CHARACTERS - EITHER THE VIN IS FAKE OR EARLIER THAN 1981
ELSE
--USE FORMULA TO CALCULATE THE CHECK DIGIT
SELECT MOD((DECODE(SUBSTR(IN_VIN,1,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,1,1))*8 +
DECODE(SUBSTR(IN_VIN,2,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,2,1))*7 +
DECODE(SUBSTR(IN_VIN,3,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,3,1))*6 +
DECODE(SUBSTR(IN_VIN,4,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,4,1))*5 +
DECODE(SUBSTR(IN_VIN,5,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,5,1))*4 +
DECODE(SUBSTR(IN_VIN,6,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,6,1))*3 +
DECODE(SUBSTR(IN_VIN,7,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,7,1))*2 +
DECODE(SUBSTR(IN_VIN,8,1) ,'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,8,1))*10 +
DECODE(SUBSTR(IN_VIN,10,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,10,1))*9 +
DECODE(SUBSTR(IN_VIN,11,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,11,1))*8 +
DECODE(SUBSTR(IN_VIN,12,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,12,1))*7 +
DECODE(SUBSTR(IN_VIN,13,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,13,1))*6 +
DECODE(SUBSTR(IN_VIN,14,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,14,1))*5 +
DECODE(SUBSTR(IN_VIN,15,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,15,1))*4 +
DECODE(SUBSTR(IN_VIN,16,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,16,1))*3 +
DECODE(SUBSTR(IN_VIN,17,1),'A',V_A,'B',V_B,'C',V_C,'D',V_D,'E',V_E,'F',V_F,'G',V_G,'H',V_H,'J',V_J,'K',V_K,'L',V_L,'M',V_M,'N',V_N,'P',V_P,'R',V_R,'S',V_S,'T',V_T,'U',V_U,'V',V_V,'W',V_W,'X',V_X,'Y',V_Y,'Z',V_Z,SUBSTR(IN_VIN,17,1))*2),11)
INTO V_CHECK_DIGIT_NUM
FROM DUAL;
--IF CHECK DIGIT IS 10, USE X ELSE WHAT EVER IS RETURNED I.E. 0-9
IF (V_CHECK_DIGIT_NUM = 10) THEN
V_CHECK_DIGIT := 'X';
ELSE
V_CHECK_DIGIT := TO_CHAR(V_CHECK_DIGIT_NUM);
END IF;
--IF THE CALCULATED CHECK DIGIT MATCHES THE 9TH CHARACTER OF VIN, RETURN SUCCESS [0] ELSE FAILURE [1]
IF (V_CHECK_DIGIT = SUBSTR(IN_VIN,9,1)) THEN
RETURN 0; --SUCCESS, THE VIN IS GENUINE
ELSE
RETURN 1; --FAILURE, CHECK DIGIT MISMATCH, THE VIN IS FAKE
END IF;
END IF;
END VALIDATE_VIN;