有這樣一個需求:需要根據輸入的編碼(這個編碼值來自於數據庫的一個表)生成下一個編碼,編碼規則如下所示(我們暫且不關心這個邏輯是否合理,只關心如何實現):
1: 最小值為A0000, 最大值為ZZZZZ
2:編碼A0000的下一個值為A0001, 編碼A9999的下一個值為B0000, 編碼AB999的下一個值為AC000,編碼AC999的下一個值為AD000,依此規則內推。
3:不用擔心輸入值為類似A09BC這樣的值,應用程序會從表裡面取編碼的最大值。應用程序也會檢查、控制輸入參數,不用在數據庫的函數(FUNCTION)裡面做檢查控制。
4:不用擔心輸入值為ac908這種值(大小寫問題),應用程序從表裡獲取編碼的值(不接受用戶輸入)。所以這個的檢查、控制也不用納入數據庫函數考慮范圍。
看到同事用ASCII循環判斷字符是否為數字,大量的邏輯處理,我覺得並不是如何高效而且有些弄復雜了,寫了下面FUN_GEN_NEXT_CODE,用正則表達式獲取數字部分,然後根據數字部分進行判斷處理。 寫完感覺也有點臃腫,因為要花大量的判斷處理邊界值(A9999 AZ999之類的邊界值),但是暫時也沒有更好的思路想法。 (ORACLE數據庫實現)
CREATE OR REPLACE FUNCTION FUN_GEN_NEXT_CODE(MAX_DEMENSION_NO VARCHAR2)
RETURN VARCHAR2
IS
CodeValue NUMBER(5);
CodeChar VARCHAR(4);
CharValue VARCHAR2(5);
ReturnCode VARCHAR2(5);
BEGIN
IF LENGTH(MAX_DEMENSION_NO) >=6 OR LENGTH(MAX_DEMENSION_NO) < 5 THEN
RETURN '';
END IF;
SELECT REGEXP_SUBSTR(MAX_DEMENSION_NO,'[[:digit:]]+') INTO CodeValue FROM DUAL;
IF LENGTH(CodeValue)= 4 THEN
IF CodeValue= 9999 THEN
IF SUBSTR(MAX_DEMENSION_NO,1,1)='Z' THEN
CharValue :='ZA';
CodeChar := '000';
ELSE
CharValue :=CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,1,1)) +1);
CodeChar := '0000';
END IF;
ELSE
CharValue :=SUBSTR(MAX_DEMENSION_NO,0,1);
CodeChar :=TRIM(TO_CHAR(CodeValue+1,'0000'));
END IF;
ReturnCode :=CharValue || CodeChar;
ELSIF LENGTH(CodeValue)=3 THEN
IF CodeValue= 999 THEN
IF SUBSTR(MAX_DEMENSION_NO,1,2)='ZZ' THEN
ReturnCode :='ZZA' || '00';
ELSE
IF SUBSTR(MAX_DEMENSION_NO,2,1) ='Z' THEN
ReturnCode := CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,1,1)) +1) || '0000';
ELSE
ReturnCode :=SUBSTR(MAX_DEMENSION_NO,1,1) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,2,1)) +1) || '000';
END IF;
END IF;
ELSE
ReturnCode :=SUBSTR(MAX_DEMENSION_NO,1,1) || TRIM(TO_CHAR(CodeValue+1,'000'));
END IF;
ELSIF LENGTH(CodeValue)=2 THEN
IF CodeValue= 99 THEN
IF SUBSTR(MAX_DEMENSION_NO,1,3) ='ZZZ' THEN
ReturnCode :='ZZZA0';
ELSE
IF SUBSTR(MAX_DEMENSION_NO,3,1) ='Z' THEN
ReturnCode := SUBSTR(MAX_DEMENSION_NO,1,1) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,2,1)) +1) + '000';
ELSE
ReturnCode := SUBSTR(MAX_DEMENSION_NO,1,2) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,3,1)) +1) || '00';
END IF;
END IF;
ELSE
ReturnCode :=SUBSTR(MAX_DEMENSION_NO,1,3) + TRIM(TO_CHAR(CodeValue+1,'00'));
END IF;
ELSIF LENGTH(CodeValue)=1 THEN
IF CodeValue= 9 THEN
IF SUBSTR(MAX_DEMENSION_NO, 1,4) ='ZZZZ' THEN
ReturnCode := 'ZZZZA';
ELSE
ReturnCode := SUBSTR(MAX_DEMENSION_NO, 1,3) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,4,1)) +1) || '0';
END IF;
ELSE
ReturnCode :=SUBSTR(MAX_DEMENSION_NO,0,4) || TRIM(TO_CHAR(CodeValue+1,'0'));
END IF;
ELSE
IF MAX_DEMENSION_NO='ZZZZZZ' THEN
ReturnCode :='ZZZZZ';
ELSE
ReturnCode :=SUBSTR(MAX_DEMENSION_NO, 1,4) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,5,1)) +1);
END IF;
END IF;
RETURN ReturnCode;
EXCEPTION
WHEN OTHERS
THEN
RETURN ('');
END FUN_GEN_NEXT_CODE;