Mysql 检查IP是否在子网中
我有一个IP地址(ipNumeric)存储为无符号整数的表a和一个子网(subnetNumeric)的表B: 我想检查此IP是否是子网的成员 子网为A类、B类和C类Mysql 检查IP是否在子网中,mysql,ip,subnet,Mysql,Ip,Subnet,我有一个IP地址(ipNumeric)存储为无符号整数的表a和一个子网(subnetNumeric)的表B: 我想检查此IP是否是子网的成员 子网为A类、B类和C类 在MySQL中,这是可以在合理的时间内动态完成的,还是应该预先计算子网范围?当然,这是可行的。其思想是,我们通过将最高有效位设置为1来计算子网掩码,其数量由子网类指定。对于C类,这将是 SELECT -1 << 8; 首先创建表以支持测试 CREATE TABLE a (ipNumeric INT UNSIGNED);
在MySQL中,这是可以在合理的时间内动态完成的,还是应该预先计算子网范围?当然,这是可行的。其思想是,我们通过将最高有效位设置为1来计算子网掩码,其数量由子网类指定。对于C类,这将是
SELECT -1 << 8;
首先创建表以支持测试
CREATE TABLE a (ipNumeric INT UNSIGNED);
INSERT INTO a (ipNumeric) VALUES(INET_ATON("172.16.40.101"));
INSERT INTO a (ipNumeric) VALUES(INET_ATON("192.168.1.12"));
INSERT INTO a (ipNumeric) VALUES(INET_ATON("10.1.5.51"));
INSERT INTO a (ipNumeric) VALUES(INET_ATON("10.7.1.78"));
CREATE TABLE b (subnetNumeric INT UNSIGNED);
INSERT INTO b (subnetNumeric) VALUES (INET_ATON("192.168.0.0"));
INSERT INTO b (subnetNumeric) VALUES (INET_ATON("10.1.0.0"));
INSERT INTO b (subnetNumeric) VALUES (INET_ATON("172.16.0.0"));
现在根据address&mask=subnet在表之间查找匹配项。这里我们假设B类子网(255.255.0.0)。不需要移位,因为我们可以使用INET_ATON()函数
SELECT INET_NTOA(a.ipNumeric),INET_NTOA(b.subnetNumeric) FROM a,b
WHERE (a.ipNumeric & INET_ATON("255.255.0.0")) = b.subnetNumeric;
+------------------------+----------------------------+
| INET_NTOA(a.ipNumeric) | INET_NTOA(b.subnetNumeric) |
+------------------------+----------------------------+
| 192.168.1.12 | 192.168.0.0 |
| 10.1.5.51 | 10.1.0.0 |
| 172.16.40.101 | 172.16.0.0 |
+------------------------+----------------------------+
这是我们使用的MySQL函数
DELIMITER $$
DROP FUNCTION IF EXISTS `ip_in_subnet_mask`$$
CREATE DEFINER=`root`@`%` FUNCTION `ip_in_subnet_mask`(ip VARCHAR(20), subnet VARCHAR(20), netmask VARCHAR(20)) RETURNS TINYINT(1)
DETERMINISTIC
BEGIN
RETURN (INET_ATON(ip) & INET_ATON(netmask)) = INET_ATON(subnet);
END$$
DELIMITER ;
e、 g.找到t.ip在192.168.0.x范围内的所有行,其中0I有一个解决方案,可以确定地址何时存储为字符串。所以,如果你想把这部分作为你算法的一部分,你可以在这里使用我的解决方案 这有点棘手,尤其是对于IPv6。在IPv6中,可以选择压缩段,如1::1,它相当于1:0:0:0:0:0:1,这是它很棘手的主要原因 将生成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();
}
乌普图特:
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)))
从表中选择行,其中(子字符串_索引(columnX,,,,,,,2)=“1.2”)
从表中选择行,其中(子字符串_索引(columnX,,:',4)=“1:2:3:4”)
从表中选择行,其中((子字符串U索引(columnX,,:'),4)='1:0:0')或((子字符串U索引(columnX,,:'),2)='1:')和(长度(columnX)-长度(替换(columnX,,:'),'')谢谢,但这取决于知道子网类吗?答案很好-但IPv6呢?这可能吗?
DELIMITER $$
DROP FUNCTION IF EXISTS `ip_in_subnet_mask`$$
CREATE DEFINER=`root`@`%` FUNCTION `ip_in_subnet_mask`(ip VARCHAR(20), subnet VARCHAR(20), netmask VARCHAR(20)) RETURNS TINYINT(1)
DETERMINISTIC
BEGIN
RETURN (INET_ATON(ip) & INET_ATON(netmask)) = INET_ATON(subnet);
END$$
DELIMITER ;
SELECT *
FROM t
WHERE
ip_in_subnet_mask(t.ip, "192.168.0.0", "255.255.255.0")
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();
}
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)))