2017-07-13 55 views
-1

尋找PL \ SQL(甲骨文ENV)轉換功能,其節選的字符串作爲輸入(IPV4格式),並返回IPV6格式,例如:PLSQL函數來IPV4轉換爲IPV6

發送 - 10.85。 79.96將返回0:0:0:0:0:ffff:a55:4f60

感謝您的幫助。

+4

我不知道你打算作什麼用途,但請注意,這樣的轉換隻適用在非常特殊的情況下(IPv6插座接受IPv4連接),並且通常IPv4和IPv6地址之間沒有可見的關係。 (只是要確保每個人閱讀這個問題都明白:) –

回答

3

您可以使用這組功能:

FUNCTION UncompressIpV6(Ip IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS 
    IpFull VARCHAR2(40); 
    len INTEGER := 7; 
BEGIN 
    IF REGEXP_LIKE(Ip, '::') THEN 
     IpFull := REGEXP_REPLACE(REGEXP_REPLACE(Ip, '^::', '0::'), '::$', '::0'); 
     IF REGEXP_LIKE(Ip, ':\d+\.\d+\.\d+\.\d+$') THEN 
      -- Mixed notation, e.g.: 0::FFFF:129.144.52.38 
      len := 6; 
     END IF; 
     WHILE REGEXP_COUNT(IpFull, ':') <= len LOOP 
      IpFull := REGEXP_REPLACE(IpFull, '::', ':0::'); 
     END LOOP; 
     RETURN REGEXP_REPLACE(IpFull, '::', ':'); 
    ELSE 
     RETURN Ip; 
    END IF; 

END UncompressIpV6; 



FUNCTION Ip2Decimal(IP IN VARCHAR2) RETURN NUMBER DETERMINISTIC IS 
    DecimalIp NUMBER := 0; 
BEGIN 

    IF REGEXP_LIKE(IP, ':') THEN 
     IF REGEXP_LIKE(IP, '\d+\.\d+\.\d+\.\d+$') THEN 
      -- Mixed notation, e.g.: 0:0:0:0:0:FFFF:129.144.52.38 
      SELECT SUM(TO_NUMBER(REGEXP_SUBSTR(UncompressIpV6(IP), '[[:xdigit:]]+', 1, LEVEL), 'XXXX') * POWER(65536, 8-LEVEL)) 
      INTO DecimalIp 
      FROM dual 
      CONNECT BY LEVEL <= 6; 

      SELECT DecimalIp + SUM(REGEXP_SUBSTR(REGEXP_SUBSTR(UncompressIpV6(IP), '\d+\.\d+\.\d+\.\d+$'), '\d+', 1, LEVEL) * POWER(256, 4-LEVEL)) 
      INTO DecimalIp 
      FROM dual 
      CONNECT BY LEVEL <= 4; 
      RETURN DecimalIp;  
     ELSE 
      SELECT SUM(TO_NUMBER(REGEXP_SUBSTR(UncompressIpV6(IP), '[[:xdigit:]]+', 1, LEVEL), 'XXXX') * POWER(65536, 8-LEVEL)) 
      INTO DecimalIp 
      FROM dual 
      CONNECT BY LEVEL <= 8; 
      RETURN DecimalIp; 
     END IF; 
    ELSE 
     SELECT SUM(REGEXP_SUBSTR(IP, '\d+', 1, LEVEL) * POWER(256, 4-LEVEL)) 
     INTO DecimalIp 
     FROM dual 
     CONNECT BY LEVEL <= 4; 
     RETURN DecimalIp; 
    END IF; 

END Ip2Decimal; 




FUNCTION Decimal2Ip(IpDecimal IN NUMBER) RETURN VARCHAR2 DETERMINISTIC IS 

    IP VARCHAR2(16); 
    Octet INTEGER; 
    v_IpDecimal INTEGER := IpDecimal; 

BEGIN 
    IF IpDecimal IS NULL THEN 
     RETURN NULL; 
    END IF; 
    IF IpDecimal > 2**32 - 1 THEN 
     RAISE NUMERIC_OVERFLOW; 
    END IF; 

    FOR i IN 1..4 LOOP 
     Octet := TRUNC(v_IpDecimal/256**(4-i)); 
     v_IpDecimal := v_IpDecimal - Octet * 256**(4-i); 
     IP := IP ||'.'||Octet; 
    END LOOP; 
    RETURN SUBSTR(IP, 2); 

END Decimal2Ip; 



FUNCTION Decimal2IPv6(IpDecimal IN NUMBER) RETURN VARCHAR2 DETERMINISTIC IS 

    IP VARCHAR2(40); 
    Octet INTEGER; 
    v_IpDecimal NUMBER := IpDecimal; 

BEGIN 
    IF IpDecimal IS NULL THEN 
     RETURN NULL; 
    END IF; 
    IF IpDecimal > 2**128 - 1 THEN 
     RAISE NUMERIC_OVERFLOW; 
    END IF; 

    FOR i IN 1..8 LOOP 
     Octet := TRUNC(v_IpDecimal/65536**(8-i)); 
     v_IpDecimal := v_IpDecimal - Octet * 65536**(8-i); 
     IP := IP ||':'||TO_CHAR(Octet, 'fmXXXX'); 
    END LOOP; 
    RETURN LOWER(SUBSTR(IP, 2)); 

END Decimal2IPv6; 

例子:

SELECT REGEXP_REPLACE(Decimal2IPv6(Ip2Decimal('10.85.79.96')), ':0:', ':ffff:', 1, 3) 
FROM dual; 

0:0:0:0:0:ffff:a55:4f60