Convertir IP entre cadena y número
Hasta donde este humilde cronista ha podido determinar, Oracle no dispone de funciones nativas para convertir direcciones IP formateadas como cadenas (v.gr. 192.168.0.100) en números enteros (v.gr. 3232235620) y a la inversa. Así que aquí tenemos unas de fabricación casera.
Como no sabía qué nombre ponerles he usado la convención de PHP: ip2long() y long2ip(). En otros lenguajes se llaman inet_aton() e inet_ntoa(), que es casi igual de confuso.
CREATE OR REPLACE FUNCTION IP2LONG (
IP_CADENA IN VARCHAR2
) RETURN NUMBER DETERMINISTIC
IS
IP1 NUMBER;
IP2 NUMBER;
IP3 NUMBER;
IP4 NUMBER;
BEGIN
/*
* Recibe una dirección IPv4 en formato cadena y devuelve el número entero correspondiente
* Devuelve NULL si no es una IP válida
*/
IF NOT REGEXP_LIKE(IP_CADENA, '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$') THEN
RETURN NULL;
END IF;
IP1 := TO_NUMBER(REGEXP_SUBSTR(IP_CADENA, '[0-9]+', 1, 1));
IP2 := TO_NUMBER(REGEXP_SUBSTR(IP_CADENA, '[0-9]+', 1, 2));
IP3 := TO_NUMBER(REGEXP_SUBSTR(IP_CADENA, '[0-9]+', 1, 3));
IP4 := TO_NUMBER(REGEXP_SUBSTR(IP_CADENA, '[0-9]+', 1, 4));
IF IP1 BETWEEN 0 AND 255 AND IP2 BETWEEN 0 AND 255 AND IP3 BETWEEN 0 AND 255 AND IP4 BETWEEN 0 AND 255 THEN
RETURN
IP1 * 16777216 + -- 2^24
IP2 * 65536 + -- 2^16
IP3 * 256 + -- 2^8
IP4; -- 2^0
ELSE
RETURN NULL;
END IF;
END IP2LONG;
/
CREATE OR REPLACE FUNCTION LONG2IP (
IP_NUMERO IN NUMBER
) RETURN VARCHAR2 DETERMINISTIC
IS
BEGIN
/*
* Recibe una dirección IPv4 en formato numérico y devuelve la cadena correspondiente
* Devuelve NULL si no es una IP válida
*/
IF IP_NUMERO BETWEEN 0 AND 4294967295 THEN -- [0, 2^32 - 1]
RETURN
BITAND(IP_NUMERO / 16777216, 255) || '.' || -- 2^24 / 2^8 - 1
BITAND(IP_NUMERO / 65536, 255) || '.' || -- 2^16 / 2^8 - 1
BITAND(IP_NUMERO / 256, 255) || '.' || -- 2^8 / 2^8 - 1
BITAND(IP_NUMERO, 255); -- 2^0 / 2^8 - 1
ELSE
RETURN NULL;
END IF;
END LONG2IP;
/
Compatibilidad
IP2LONG() utiliza expresiones regulares así que requiere Oracle 10 o superior.