Java Oracle数据库中的分层文本搜索
Table=BLOCK在这两列中都有复合唯一索引Java Oracle数据库中的分层文本搜索,java,oracle,Java,Oracle,Table=BLOCK在这两列中都有复合唯一索引 IP_ADDRESS CIDR_SIZE ========= ========== 10.10 16 15.0 16 67.7 16 18.0 8 要求: 不允许使用子块。例如,67.7.1和24是不允许的,因为这是67.7的孩子。换句话说,若数据库中有任何IP地址与新IP的开始部分匹配,那个么它应该失败。我是否可以使用Oracle SQL查询来执行此操作? 我正
IP_ADDRESS CIDR_SIZE
========= ==========
10.10 16
15.0 16
67.7 16
18.0 8
要求:
不允许使用子块。例如,67.7.1和24是不允许的,因为这是67.7的孩子。换句话说,若数据库中有任何IP地址与新IP的开始部分匹配,那个么它应该失败。我是否可以使用Oracle SQL查询来执行此操作?
我正在考虑通过
选择内存中的所有记录。
将每个IP转换为其二进制位
10.10=00001010.00001010
15.0 = 00001111.00000000
67.7 = 01000011.00000111
18.0=00010010.00000000
将新IP转换为二进制位。67.7.1=01000011.00000111.00000001
检查新的IP二进制位是否从现有IP二进制位开始。
如果为true,则新记录存在于数据库中。
例如,新二进制位01000011.0000111.00000001确实以现有ip 67.7二进制位01000011.0000011开始。其余记录不匹配。
我想看看是否有一个Oracle查询可以帮我做到这一点,即从数据库返回匹配的IP地址。我查看了Oracle的文本API,但还没有找到任何内容。您为什么不能使用INSTR函数? 我会做一些类似NOT EXISTS子句的事情,检查INSTRb_outer.IP_ADDRESS,b_inner.IP_ADDRESS 1
*编辑:考虑到这一点,您可能需要检查结果是否为1,这意味着潜在的IP地址从现有IP地址的第一个字符开始匹配,而不是像我最初使用的一般子字符串搜索。是的,您可以在SQL中将IP转换为数字,然后确保这不是一个错误使用较小的cidr大小记录,该大小在使用其cidr大小时提供相同的ipnum
如果位数不在8的因数上重叠,Instr将无法工作。e、 g.10.224/11是10.240/12的父母,但不是10.176/12谢谢。我不介意在表中添加另一列,将ip_地址作为其二进制位格式,如果这有助于我仅使用一个查询来实现这一点的话,可能与LIKE子句相反。
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