Mysql 检查IP是否在子网中

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);

我有一个IP地址(ipNumeric)存储为无符号整数的表a和一个子网(subnetNumeric)的表B:

我想检查此IP是否是子网的成员

子网为A类、B类和C类


在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)))