我正在寻找一个select语句,它将检查2个IP地址是否在同一个子网中,具体取决于掩码主机部分中的位数。我找到this excellent question并回答,但它仅适用于IPv4地址。
我对IPv4的MySQL语句如下,其中3是掩码主机部分(21位网络)中的位数:
SELECT FROM table WHERE ((-1 << 3) & INET_ATON(IPADDRESS1) = (-1 << 3) & INET_ATON(IPADDRESS2))
任何人都可以创建IPv6等价物吗? (这甚至超出了我的努力)。我意识到有一个INET6_ATON,但我用来创建上面1的掩码的-1将无效(由于长度),以及可能的其他原因。
如果有帮助,我们可以假设IPv6地址是RFC 5952格式,或者是完整的8个冒号分隔数字。
答案 0 :(得分:0)
这里有很多问题。大多数答案都是here和reference implementation for IPv6
在你向我吐口水以获得仅限链接的答案之前,这里有一些关于发生了什么的提示。
链接是指处理非重叠范围(如IP地址)的有效方法。但是,部分解决方案是能够从128位值中加/减1。请参阅函数IpIncr
和IpDecr
。
为了制作面具,我建议转换为32个字符的十六进制,然后使用子串。请参阅CONCAT, LEFT, RIGHT, REPEAT
等。完成此操作后,字符串比较应轻松处理网络&#34;中的&#34;。
MySQL 8.0中的代码会更简单,因为BLOBs
可以被视为真正的长字符串;之前的比特限制为BIGINT
,这对于IPv6来说还不够大。
答案 1 :(得分:0)
我有一个地址存储为字符串的解决方案。
类似的问题是找到数据库中属于特定子网的所有地址,这与此处发布的问题非常类似,以检查两个地址是否在同一子网中。
这有点棘手,特别是对于IPv6。在IPv6中,可以选择压缩段,例如1 :: 1,相当于1:0:0:0:0:0:0:1,这是它很棘手的主要原因。
The IPAddress Java library将生成mysql SQL以搜索给定子网中的地址。该链接更详细地描述了该问题。免责声明:我是项目经理。
基本算法是获取子网地址的网络部分,然后获取该部分的每个变体(例如,上面的两个字符串是完整地址1 :: 1的变体),然后计算段分隔符的数量,然后对匹配的地址执行mysql子字符串,还要计算匹配地址中的总分隔符。
以下是示例代码:
public static void main(String[] args) throws IPAddressStringException {
System.out.println(getSearchSQL("columnX", "1.2.3.4/16"));
System.out.println(getSearchSQL("columnX", "1:2:3:4:5:6:7:8/64"));
System.out.println(getSearchSQL("columnX", "1::8/64"));
}
static String getSearchSQL(String expression, String ipAddressStr) throws IPAddressStringException {
IPAddressString ipAddressString = new IPAddressString(ipAddressStr);
IPAddress ipAddress = ipAddressString.toAddress();
IPAddressSection networkPrefix = ipAddress.getNetworkSection(ipAddress.getNetworkPrefixLength(), false);
StringBuilder sql = new StringBuilder("Select rows from table where ");
networkPrefix.getStartsWithSQLClause(sql, expression);
return sql.toString();
}
Ouptut:
Select rows from table where (substring_index(columnX,'.',2) = '1.2')
Select rows from table where (substring_index(columnX,':',4) = '1:2:3:4')
Select rows from table where ((substring_index(columnX,':',4) = '1:0:0:0') OR ((substring_index(columnX,':',2) = '1:') AND (LENGTH (columnX) - LENGTH(REPLACE(columnX, ':', '')) <= 5)))