表= BLOCK(两列都有复合唯一索引)
IP_ADDRESS CIDR_SIZE
========= ==========
10.10 16
15.0 16
67.7 16
18.0 8
要求:
我想通过......来做这件事。
将每个IP转换为二进制位
10.10 = 00001010.00001010
15.0 = 00001111.00000000
67.7 = 01000011.00000111
18.0 = 00010010.00000000
将新IP转换为二进制位。 67.7.1 = 01000011.00000111.00000001
01000011.00000111.00000001
确实以现有的ip(67.7)二进制位01000011.00000111
开始。其余记录不匹配。 我正在查看是否有可以为我执行此操作的Oracle查询,即从数据库返回匹配的IP地址。我检查了Oracle的Text API,但还没有找到任何东西。
答案 0 :(得分:0)
你有没有理由不能使用INSTR功能? http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions068.htm#i77598
我会执行类似于检查NOT EXISTS
INSTR(b_outer.IP_ADDRESS,b_inner.IP_ADDRESS) <> 1
子句
*编辑:考虑到这一点,您可能需要检查结果是否为1(意味着潜在的IP地址与现有IP地址的第一个字符匹配),而不是一般的子字符串搜索。最初有它。
答案 1 :(得分:0)
是的,您可以通过将IP转换为数字来在SQL中执行此操作,然后确保这不是具有较小cidr
大小的记录,在使用其cidr
大小时提供相同的ipnum。
WITH ipv AS
( SELECT IP.*
, NVL(REGEXP_SUBSTR( ip, '\d+', 1, 1 ),0) * 256 * 256 * 256 -- octet1
+ NVL(REGEXP_SUBSTR( ip, '\d+', 1, 2 ),0) * 256 * 256 -- octet2
+ NVL(REGEXP_SUBSTR( ip, '\d+', 1, 3 ),0) * 256 -- octet3
+ NVL(REGEXP_SUBSTR( ip, '\d+', 1, 4 ),0) AS ipnum -- octet4
, 32-bits AS ignorebits
FROM ips IP
)
SELECT IP1.ip, IP1.bits
FROM ipv IP1
WHERE NOT EXISTS
( SELECT 1
FROM ipv IP2
WHERE IP2.bits < IP1.bits
AND TRUNC( IP2.ipnum / POWER( 2, IP2.ignorebits ) )
= TRUNC( IP1.ipnum / POWER( 2, IP2.ignorebits ) )
)
注意:我的示例使用与您的表相同的表:
SQL> desc ips
Name Null? Type
----------------------------------------- -------- ----------------------------
IP NOT NULL VARCHAR2(16)
BITS NOT NULL NUMBER