我有src_ip(varchar2)列。我需要像这样选择ip范围:
100.64.0.0/10 - > 100.64.0.0 - 100.127.255.255
我尝试编码到ip地址,但它不适合我。我怎么能这样做?
答案 0 :(得分:0)
前段时间我创建了一个包含与IP地址相关的功能的包(仅限IPv4)。使用此包,您应该能够编写查询。
CREATE OR REPLACE PACKAGE BODY IP_Utils AS
BASE_BIN CONSTANT INTEGER := 2;
BASE_OCT CONSTANT INTEGER := 8;
BASE_DEC CONSTANT INTEGER := 10;
BASE_HEX CONSTANT INTEGER := 16;
/**
* 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;
/**
* Convert a IPv4 AP-Address into decimal value
* @param IP The IP-Address, e. g. '10.151.20.224'
* @return The decimal equivalent
*/
FUNCTION Ip2Decimal(IP IN VARCHAR2) RETURN INTEGER DETERMINISTIC IS
DecimalIp NUMBER := 0;
BEGIN
IF Ip IS NULL THEN
RETURN NULL;
END IF;
FOR i IN 1..4 LOOP
DecimalIp := DecimalIp + REGEXP_SUBSTR(IP, '\d+', 1, i) * 256**(4-i);
END LOOP;
RETURN DecimalIp;
END Ip2Decimal;
/**
* Convert an IP-Address from decimal value into IPv4 format
* @param IpDecimal Decimal IP-Address, 0..4294967295
* @return The IP in IPv4 format
*/
FUNCTION Decimal2Ip(IpDecimal IN INTEGER) 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;
/**
* Determines 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
CIDR INTEGER;
SubnetDec INTEGER;
BEGIN
IF SubnetMask IS NULL OR Ip IS NULL THEN
RETURN;
END IF;
FOR i IN 1..4 LOOP
Subnet := Subnet ||'.'||BITAND(REGEXP_SUBSTR(Ip, '\d+', 1, i), REGEXP_SUBSTR(SubnetMask, '\d+', 1, i));
END LOOP;
Subnet := SUBSTR(Subnet, 2);
CIDR := SubnetMask2CIDR(SubnetMask);
SubnetDec := Ip2Decimal(Subnet);
FOR i IN CIDR..31 LOOP
SubnetDec := SubnetDec + 2**(31-i);
END LOOP;
BroadcastIp := Decimal2Ip(SubnetDec);
END GetIpSubnet;
/**
* Returns SubnetMask of given IP-Address
* @param Ip IP-Address with CIDR, e.g. 10.152.10.17/27
* @return SubnetMask, e.g. 255.255.255.224
*/
FUNCTION GetSubnetMask(Ip IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
IF Ip IS NULL OR NOT REGEXP_LIKE(Ip, '/\d{1,2}$') THEN
RETURN NULL;
END IF;
RETURN CIDR2SubnetMask(REGEXP_SUBSTR(Ip, '\d{1,2}$'));
END GetSubnetMask;
/**
* Returns Subnet of given IP-Address
* @param Ip IP-Address, e.g. 10.152.10.17
* @param SubnetMask SubnetMask in IPv4 Format, e.g. 255.255.0.0
* @return Subnet in IPv4 Format, e.g. 10.152.0.0
*/
FUNCTION GetSubnetIp(Ip IN VARCHAR2, SubnetMask IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS
Subnet VARCHAR2(16);
BroadcastIp VARCHAR2(16);
BEGIN
GetIpSubnet(Ip, SubnetMask, Subnet, BroadcastIp);
RETURN Subnet;
END GetSubnetIp;
/**
* Returns Broadcast of given IP-Address
* @param Ip IP-Address, e.g. 10.152.10.17
* @param SubnetMask SubnetMask, e.g. 255.255.0.0
* @return Broadcast in IPv4 Format, e.g. 10.152.255.255
*/
FUNCTION GetBroadcastIp(Ip IN VARCHAR2, SubnetMask IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS
Subnet VARCHAR2(16);
BroadcastIp VARCHAR2(16);
BEGIN
GetIpSubnet(Ip, SubnetMask, Subnet, BroadcastIp);
RETURN BroadcastIp;
END GetBroadcastIp;
/**
* Returns Subnet of given IP-Address
* @param Ip IP-Address with CIDR, e.g. 10.152.10.17/16
* @return Subnet in IPv4 Format, e.g. 10.152.0.0
*/
FUNCTION GetSubnetIp(Ip IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS
Subnet VARCHAR2(16);
BroadcastIp VARCHAR2(16);
SubnetMask VARCHAR2(16);
BEGIN
SubnetMask := GetSubnetMask(Ip);
GetIpSubnet(REGEXP_REPLACE(Ip,'/.+$'), SubnetMask, Subnet, BroadcastIp);
RETURN Subnet;
END GetSubnetIp;
/**
* Returns Broadcast of given IP-Address
* @param Ip IP-Address with CIDR, e.g. 10.152.10.17/16
* @return Broadcast in IPv4 Format, e.g. 10.152.255.255
*/
FUNCTION GetBroadcastIp(Ip IN VARCHAR2) RETURN VARCHAR2 DETERMINISTIC IS
Subnet VARCHAR2(16);
BroadcastIp VARCHAR2(16);
SubnetMask VARCHAR2(16);
BEGIN
SubnetMask := GetSubnetMask(Ip);
GetIpSubnet(REGEXP_REPLACE(Ip,'/.+$'), SubnetMask, Subnet, BroadcastIp);
RETURN BroadcastIp;
END GetBroadcastIp;
/**
* Translate SubnetMask to CIDR
* @param SubnetMask SubnetMask in IPv4 Format, e.g. 255.255.255.240
* @return CIDR value, e.g. 26
*/
FUNCTION SubnetMask2CIDR(SubnetMask VARCHAR2) RETURN INTEGER DETERMINISTIC IS
IpBin CHAR(32);
BEGIN
IF SubnetMask IS NULL THEN
RETURN NULL;
END IF;
IpBin := Dec2Base(Ip2Decimal(SubnetMask), BASE_BIN);
IF REGEXP_LIKE(IpBin, '^1+0+$') THEN
RETURN REGEXP_INSTR(IpBin, '0')-1;
ELSIF REGEXP_LIKE(IpBin, '^1{32}$') THEN
RETURN 32;
ELSE
RAISE VALUE_ERROR;
END IF;
END SubnetMask2CIDR;
/**
* Translate CIDR to SubnetMask
* @param CIDR Subnet, e.g. 26
* @return SubnetMask in IPv4 Format, e.g 255.255.255.240
*/
FUNCTION CIDR2SubnetMask(CIDR IN INTEGER) RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
IF CIDR IS NULL THEN
RETURN NULL;
END IF;
IF CIDR NOT BETWEEN 1 AND 32 THEN
RAISE VALUE_ERROR;
END IF;
RETURN Decimal2Ip(Base2Dec(RPAD(LPAD('0', CIDR+1, '1'), 32, '0'), BASE_BIN));
END CIDR2SubnetMask;
END IP_Utils;
/