短網址實作二-演算法

摘要:短網址實作二-演算法

IF EXISTS (SELECT NAME FROM sys.objects WHERE NAME = 'NGIS_FUN_MD5' AND TYPE IN (N'FN', N'IF', N'TF', N'FS', N'FT'))
--IF OBJECT_ID(N'NGIS_GetURLKey', N'FN') IS NOT NULL
DROP FUNCTION dbo.NGIS_FUN_MD5
GO
CREATE FUNCTION dbo.NGIS_FUN_MD5 (@P_cURL nchar(2500))
RETURNS @TMP_MD5 TABLE   (
                 iCOUNT int,
                 cCODE  char(8)
)      
--WITH ENCRYPTION
-- =============================================
--用途   : 產生短網址的演算法
--傳入值 : 原始網址
--傳出值 : 四組短網址
--版次   : 2012/6/13 Renee  Modify
--
--
-- =============================================
AS BEGIN

DECLARE @P_cMD5        char(34),       
        @P_iN          int,
        @P_iP          int,
        @P_cTMPString  char(8),
        @P_iTMPInt     bigint,
        @P_iINDEX      bigint,
        @P_cOutCHAR    char(8)

SELECT @P_cMD5=SYS.FN_SQLVARBASETOSTR(HashBytes('MD5', RTRIM(@P_cURL)));

/*
演算法說明

1.  將長網址用md5演算法生成32位簽名串,分為4段,,每段8個字元。

2.  對這4段循環處理,取每段的8個字元, 將他看成16進位字元串與0x3fffffff(30位1)的位移操作,超過30位的忽略處理。 

3.  將每段得到的值又分成6段,得到其在字元數組中的索引並取出拼串。

4.  這樣一個md5字元串可以獲得4個6位串,取里面的任意一個就可作為這個長url的短url地址。
*/

SELECT @P_iN=0

WHILE (@P_iN<4) BEGIN
  --把加密字元按照 8 位一組 16 進位與 0x3FFFFFFF 進行位與運算
  SELECT @P_cTMPString=SUBSTRING(@P_cMD5,@P_iN*8+3,8);

  SELECT @P_iTMPInt=CONVERT(bigint,CONVERT(varbinary(100),'0x3FFFFFFF'+@P_cTMPString)) ;

  SET @P_cOutCHAR='';
  --循環獲得每組6位的字元串
  SELECT @P_iP=0

  WHILE (@P_iP<6) BEGIN

    SELECT @P_iINDEX=@P_iTMPInt%62;

    SELECT @P_cOutCHAR=RTRIM(@P_cOutCHAR)+cCODE FROM SHORTER_ARRAY WHERE iINDEX=@P_iINDEX;

    SELECT @P_iTMPInt=@P_iTMPInt/(POWER(2,5)); --等同右移5位 @P_iTMPInt1>>5

    SET @P_iP=@P_iP+1;

  END

  INSERT INTO @TMP_MD5 SELECT @P_iN,@P_cOutCHAR;

  SET @P_iN=@P_iN+1;

END 

  RETURN

END