MySQL提供的一个巧妙的技巧是位移。您可以使用它来查看IP是否包含在以cidr表示法写的地址块中。您可以使用此方法将您的地址视为X.X.X.X/16 cidr块。
set @cidr_block:='10.20.30.40/16';
select inet_ntoa(inet_aton(substring_index(@cidr_block,'/',1))>>(32-substring_index(@cidr_block,'/',-1))<<(32-substring_index(@cidr_block,'/',-1))) as first_ip,
inet_aton(substring_index(@cidr_block,'/',1))>>(32-substring_index(@cidr_block,'/',-1))<<(32-substring_index(@cidr_block,'/',-1)) as first_ip_num,
inet_ntoa((((inet_aton(substring_index(@cidr_block,'/',1))>>(32-substring_index(@cidr_block,'/',-1)))+1)<<(32-substring_index(@cidr_block,'/',-1)))-1) as last_ip,
(((inet_aton(substring_index(@cidr_block,'/',1))>>(32-substring_index(@cidr_block,'/',-1)))+1)<<(32-substring_index(@cidr_block,'/',-1)))-1 as last_ip_num
;
+-----------+--------------+---------------+-------------+
| first_ip | first_ip_num | last_ip | last_ip_num |
+-----------+--------------+---------------+-------------+
| 10.20.0.0 | 169082880 | 10.20.255.255 | 169148415 |
+-----------+--------------+---------------+-------------+
1 row in set (0.00 sec)
查看ip是否在地址块中的捷径 - 简单地筛选cidr地址和ip以查看它们是否相同。当然,如果应用于存储的值,这将是表扫描。
select inet_aton('127.0.0.1')>>16 = inet_aton('127.0.10.20')>>16 as `1 = true`;
+----------+
| 1 = true |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)
select inet_aton('127.0.0.1')>>16 = inet_aton('127.10.10.20')>>16 as `0 = false`;
+-----------+
| 0 = false |
+-----------+
| 0 |
+-----------+
1 row in set (0.00 sec)
你不这样做,通配符只对文本有意义。你会搜索一个很好的旧的“BETWEEN”范围。 –
@ÁlvaroGonzález如果我将192.168.1.1这样的IP地址存储为192168001001(int 12)而不是包含点并使用varchar(15),那么这是一种不错的方法吗?然后我可以做通配符搜索。 –
这样你就可以获得字符串比较的效率和二进制流的可读性。给我一分钟,我想我会写一个答案。 –