Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何在MySQL中存储(并查找)带有通配符的字符串?_Php_Mysql - Fatal编程技术网

Php 如何在MySQL中存储(并查找)带有通配符的字符串?

Php 如何在MySQL中存储(并查找)带有通配符的字符串?,php,mysql,Php,Mysql,我需要存储一个带有通配符的IP地址,比如10.0.%.1。然后,我希望从我的查询中找到IP地址在允许范围(10.0.0-255.1)内的任何人 你们能帮帮我吗?我曾尝试存储10.0.%.1,但在使用LIKE查询时找不到它(我甚至不知道这是否是实现它的方法—可能不是) 提前谢谢。将ip地址保存为数据库中的4个整数,如下所示: IPpart1 IPpart2 IPpart3 IPpart4 ------------------------------- 127 0 0

我需要存储一个带有通配符的IP地址,比如10.0.%.1。然后,我希望从我的查询中找到IP地址在允许范围(10.0.0-255.1)内的任何人

你们能帮帮我吗?我曾尝试存储10.0.%.1,但在使用LIKE查询时找不到它(我甚至不知道这是否是实现它的方法—可能不是)


提前谢谢。

将ip地址保存为数据库中的4个整数,如下所示:

IPpart1 IPpart2 IPpart3 IPpart4
-------------------------------
127     0       0       1
并使其可为空。(NULL将成为我们的通配符)

然后可以对数据库执行如下查询:

SELECT * FROM iptable WHERE (IPpart1 IS NULL OR IPpart1 = '$firstpart') AND (IPpart2 IS NULL OR IPpart2 = '$secondpart') AND (IPpart3 IS NULL OR IPpart3 = '$thirdpart') AND (IPpart4 IS NULL OR IPpart4 = '$fourthpart')
SELECT * FROM networks
WHERE ip & mask = INET_ATON('10.0.23.1') & mask
这是一个有点冗长的一点,它得到了工作完成


甚至可以从一个普通的IP字段构造一个具有该结构的临时表,但如果您有许多请求,这将是一个很大的开销。

将IP地址转换为32位整数,并为地址和掩码创建一列。您可以使用
INET\u NTOA()
INET\u ATON()
函数。您的10.0.%.1范围可以表示为网络10.0.0.1,掩码为255.255.0.255。要查看给定的IP地址是否与此网络匹配,请将掩码应用于IP地址,并将其与网络地址进行比较。如果它们匹配,则地址在网络中。例如,如果要测试10.0.4.1,请使用按位AND对其应用掩码:

10.0.4.1 & 255.255.0.255 = 10.0.0.1
这与您的网络地址匹配,因此此IP位于网络中

您可以将此网络存储在表中,如下所示(ip和掩码是整数):

您可以找到给定IP(10.0.23.1)是否与以下匹配:

SELECT * FROM iptable WHERE (IPpart1 IS NULL OR IPpart1 = '$firstpart') AND (IPpart2 IS NULL OR IPpart2 = '$secondpart') AND (IPpart3 IS NULL OR IPpart3 = '$thirdpart') AND (IPpart4 IS NULL OR IPpart4 = '$fourthpart')
SELECT * FROM networks
WHERE ip & mask = INET_ATON('10.0.23.1') & mask
但是,如果您希望IP具有可读性,这将选择IP作为整数:

SELECT id, INET_NTOA(ip) AS ipstring, INET_NTOA(mask) AS maskstring
FROM networks
WHERE ip & mask = INET_ATON('10.0.23.1') & mask

这允许您测试单个给定IP地址是否与网络匹配。如果您想测试一系列IP,您必须将掩码应用于该范围内的每个IP,并按照上面的步骤测试每个IP。您可以在一个查询中完成,它只需列出您正在测试的每个IP地址。

我仔细查看了MySQL文档页面,发现了一篇适合您需要的帖子:

SELECT '10.0.0.1' AS IP0,
( SUBSTRING_INDEX( '10.0.0.1', '.', 1 ) * 16777216 +
SUBSTRING_INDEX(SUBSTRING_INDEX( '10.0.0.1', '.', 2 ),'.',-1) * 65536 +
SUBSTRING_INDEX(SUBSTRING_INDEX( '10.0.0.1', '.', -2 ),'.',1) * 256 +
SUBSTRING_INDEX( '10.0.0.1', '.', -1 )
),
'10.0.255.1' AS IP1,
    ( SUBSTRING_INDEX( '10.0.255.1', '.', 1 ) * 16777216 +
    SUBSTRING_INDEX(SUBSTRING_INDEX( '10.0.255.1', '.', 2 ),'.',-1) * 65536 +
    SUBSTRING_INDEX(SUBSTRING_INDEX( '10.0.255.1', '.', -2 ),'.',1) * 256 +
    SUBSTRING_INDEX( '10.0.255.1', '.', -1 )
) AS IP2Num1
为每个IP返回一个数值:

Ip:  |  10.0.0.1  | 10.0.255.1 |
--------------------------------
Num: | 167772161  | 167837441  |
换言之:

SELECT foo 
FROM bar.foobar
WHERE ( SUBSTRING_INDEX( ipField, '.', 1 ) * 16777216 +
    SUBSTRING_INDEX(SUBSTRING_INDEX( ipField, '.', 2 ),'.',-1) * 65536 +
    SUBSTRING_INDEX(SUBSTRING_INDEX( ipField, '.', -2 ),'.',1) * 256 +
    SUBSTRING_INDEX( ipField, '.', -1 )
) BETWEEN 167772161 AND 167837441;

你可以这样做:

我使用以下查询对其进行了测试:

SELECT IF ('10.0.12.1' LIKE '10.0.%.1'
       AND (CAST
             (REPLACE( SUBSTRING_INDEX('10.0.12.1','.',3),
                 CONCAT(SUBSTRING_INDEX('10.0.12.1','.',2),'.')
              ,'')
            AS UNSIGNED) BETWEEN 0 AND 255),
      TRUE,
      FALSE);
它返回
1
,但老实说,这有点假,不是吗?为什么不简单地:

WHERE ipField REGEXP '10\\.0\\.[0-9]{1,3}\\.1'

您可以稍微调整一下这个表达式,但基本上,在我看来,这是查询这些IP地址的最简单方法。
有关MySQL字符串函数(几乎总是很难编写)的更多信息,请参见

为什么要将值存储为%?使用大于255的数字(如
350
)并用php中的通配符替换它?您希望如何使用通配符?10.0.1%.1和10%也被认为是有效的吗?是的,10.0%可能也会这样做。除了第一部分,我不知道IP地址,不管它们叫什么。有趣的是,有没有可能像这样查询一系列IP地址?如果在int1和int2之间使用
,则表示范围从
10.0.12.1
10.0.123.2
?不,不能这样做。您必须将掩码应用于范围内的每个IP地址,然后将其与网络地址进行比较。这是因为网络掩码可以在其中有孔,并且即使您的范围的两端都在网络中,在该范围的中间的一些地址可能不是。例如,对于10.0.0.1网络,如果我的掩码为255.255.2.255,IPS10.0.0.1、10.0.4.1和10.0.5.1将在网络中,但10.0.2.1和10.0.3.1不会。INET_ATOM('10.0.20.1')和mask与INET_ATOM('10.0.50.1')和mask会不会工作?我看没有理由不这样做,最坏的情况是你需要某种类型的连接,但除非我遗漏了什么,否则它会工作,对吗?如果你的网络是10.0.0.1,掩码是255.255.8.255,那么
ip&mask
是10.0.0.1,
10.0.20.1&mask
是10.0.0.1(匹配),
10.0.50.1&mask
是10.0.0.0.1(匹配),但是<代码> 100.30.1和掩码是0.0.81(不匹配),所以即使您的表达式之间是真的,在该范围的中间有一个地址不匹配。但是,它不是我在这个场景中使用的,因为我需要不同范围的IP(LAN和WAN IP)。与其使用所有的
子字符串索引()
函数将字符串IP转换为整数,您只需使用
INET\u ATON()
。我在发布后阅读了您的答案,投票通过-也许OP想知道实现您的答案是否需要他更改表,并允许他使用
BETWEEN
查询一系列IP。。。也许你想编辑你的答案来反思一下。IMO,你的答案就是,但我在这里给出了一些可能对某些ppl有用的链接,但我再说一遍:你提供了手头问题的最佳答案谢谢,用表格模式更新了我的答案,并对一系列IP进行了测试。感谢不同的方法-这对我来说非常有用,而且设置起来非常简单。