Nie ma bezpośredniego sposobu, aby to uzyskać. Najpierw musisz podzielić IP na 4 oktety, a następnie przekonwertować z Binary -> Decimal i odwrotnie.
Jakiś czas temu stworzyłem Pakiet do takiego zadania. Poniżej widzisz tylko treść pakietu, która powinna zawierać wszystko, aby rozwiązać Twój problem.
CREATE OR REPLACE TYPE NUMBER_TABLE_TYPE AS TABLE OF NUMBER;
CREATE OR REPLACE PACKAGE BODY IP_Utility AS
BASE_BIN CONSTANT PLS_INTEGER := 2;
BASE_OCT CONSTANT PLS_INTEGER := 8;
BASE_DEC CONSTANT PLS_INTEGER := 10;
BASE_HEX CONSTANT PLS_INTEGER := 16;
NUMERIC_OVERFLOW EXCEPTION;
PRAGMA EXCEPTION_INIT(NUMERIC_OVERFLOW, -1426);
/**
* Function translate a array to PL/SQL Table
* @param Sperator String that separates elements, e.g. ';'
* @return Table of elements (NUMBER)
*/
FUNCTION SplitNumber(LIST IN VARCHAR2, Separator IN VARCHAR2) RETURN NUMBER_TABLE_TYPE IS
OutTable NUMBER_TABLE_TYPE;
BEGIN
IF LIST IS NULL THEN
RETURN NULL;
ELSE
SELECT TRIM(REGEXP_SUBSTR(LIST, '[^'||Separator||']+', 1, LEVEL))
BULK COLLECT INTO OutTable
FROM dual
CONNECT BY REGEXP_SUBSTR(LIST, '[^'||Separator||']+', 1, LEVEL) IS NOT NULL;
END IF;
IF OutTable.COUNT > 0 THEN
RETURN OutTable;
ELSE
RETURN NULL;
END IF;
END SplitNumber;
/**
* Convert a decimal nubmer into a binary/octal/hex string
* @param DecN Integer decimal number
* @param Base The binary base (BASE_BIN, BASE_OCT, BASE_HEX)
* @return The binary/octal/hex string
*/
FUNCTION Dec2Base(DecN IN INTEGER, Base IN PLS_INTEGER DEFAULT BASE_HEX) RETURN VARCHAR2 DETERMINISTIC IS
HexString CONSTANT CHAR(16) := '0123456789ABCDEF';
DecNumber INTEGER := DecN;
BaseString VARCHAR2(128) := NULL;
BEGIN
IF DecN IS NULL THEN
RETURN NULL;
END IF;
IF Base > 16 THEN
RAISE NUMERIC_OVERFLOW;
END IF;
LOOP
BaseString := SUBSTR(HexString, MOD(DecNumber, Base) + 1, 1 ) || BaseString;
DecNumber := TRUNC(DecNumber / Base);
EXIT WHEN DecNumber = 0;
END LOOP;
RETURN BaseString;
END Dec2Base;
/**
* Convert a binary/octal/hex number into a decimal value
* @param BaseString The binary/octal/hex string
* @param Base The binary base (BASE_BIN, BASE_OCT, BASE_HEX)
* @return The decimal number
*/
FUNCTION Base2Dec(BaseString IN VARCHAR2, Base IN PLS_INTEGER DEFAULT BASE_HEX) RETURN INTEGER DETERMINISTIC IS
BaseNumber INTEGER := 0;
HexString CONSTANT CHAR(16) := '0123456789ABCDEF';
BEGIN
IF Base > 16 THEN
RAISE NUMERIC_OVERFLOW;
END IF;
IF BaseString IS NULL THEN
RETURN NULL;
END IF;
FOR i IN 1..LENGTH(BaseString) LOOP
BaseNumber := BaseNumber * Base + INSTR(HexString, UPPER(SUBSTR(BaseString, i, 1))) - 1;
END LOOP;
RETURN BaseNumber;
END Base2Dec;
/**
* Returns SubnetMask of given IP Address
* @param Ip IP-Address with CIDR, e.g. '10.152.10.17/27'
* @return SubnetMask The Subnet Mask in IPv4 Format, e.g. '255.255.255.224'
*/
FUNCTION GetSubnetMask(Ip IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS
SubnetMask VARCHAR2(16);
MaskBin VARCHAR2(32);
BEGIN
IF Ip IS NULL OR NOT REGEXP_LIKE(Ip, '/\d+$') THEN
RETURN NULL;
END IF;
FOR i IN 1..REGEXP_REPLACE(Ip, '.+/') LOOP
MaskBin := MaskBin || '1';
END LOOP;
MaskBin := RPAD(MaskBin, 32, '0');
FOR i IN 1..4 LOOP
SubnetMask := SubnetMask ||'.'||Base2Dec(SUBSTR(MaskBin, 8*(i-1)+1, 8 ), BASE_BIN);
END LOOP;
SubnetMask := SUBSTR(SubnetMask, 2);
RETURN SubnetMask;
END GetSubnetMask;
/**
* Returns Subnet and Broadcast-IP of given IP Address
* @param Ip IP-Address, e.g. 10.152.10.17
* @param SubnetMask The SubnetMask, e.g. 255.255.255.240
* @param Subnet Subnet-IP: e.g. 10.152.10.16
* @param BroadcastIp Broadcast-IP: e.g. 10.152.10.31
*/
PROCEDURE GetIpSubnet(Ip IN VARCHAR2, SubnetMask IN VARCHAR2, Subnet OUT VARCHAR2, BroadcastIp OUT VARCHAR2) IS
SubnetBin VARCHAR2(8);
BroadcastBin VARCHAR2(8);
Ip_Array NUMBER_TABLE_TYPE;
Mask_Array NUMBER_TABLE_TYPE;
BEGIN
IF SubnetMask IS NULL OR Ip IS NULL THEN
RETURN;
END IF;
Ip_Array := SplitNumber(Ip, '.');
Mask_Array := SplitNumber(SubnetMask, '.');
FOR i IN 1..4 LOOP
SubnetBin := NULL;
BroadcastBin := NULL;
FOR m IN 1..8 LOOP
IF SUBSTR(LPAD(Dec2Base(Ip_Array(i), BASE_BIN), 8, '0'), m, 1) = 1
AND SUBSTR(LPAD(Dec2Base(Mask_Array(i), BASE_BIN), 8, '0'), m, 1) = 1 THEN
SubnetBin := SubnetBin ||'1';
ELSE
SubnetBin := SubnetBin ||'0';
END IF;
IF SUBSTR(LPAD(Dec2Base(Mask_Array(i), BASE_BIN), 8, '0'), m, 1) = 1 THEN
BroadcastBin := SubnetBin;
ELSE
BroadcastBin := BroadcastBin ||'1';
END IF;
END LOOP;
Subnet := Subnet ||'.'||Base2Dec(SubnetBin, BASE_BIN);
BroadcastIp := BroadcastIp ||'.'||Base2Dec(BroadcastBin, BASE_BIN);
END LOOP;
Subnet := SUBSTR(Subnet, 2);
BroadcastIp := SUBSTR(BroadcastIp, 2);
END GetIpSubnet;
END IP_Utility;
/
Lub zobacz zaawansowaną wersję tego pakietu pod adresem oracle PL/SQL jak obliczyć zakres ip dla cidr IPv6