5

10.0.%.1 のように、ワイルドカードを含む IP アドレスを保存する必要があります。次に、許可された範囲 (10.0.0-255.1) 内の IP アドレスを持つ人がクエリから見つかるようにします。

皆さん、私を助けてくれませんか? 10.0.%.1 を保存しようとしましたが、LIKE クエリでそれを見つけることができません (それがその方法であるかどうかさえわかりません - おそらくそうではありません)。

前もって感謝します。

4

3 に答える 3

3

IP アドレスを 32 ビット整数に変換し、アドレスとマスクの列を作成します。INET_NTOA()およびINET_ATON()機能を使用できます。10.0.%.1 の範囲は、255.255.0.255 のマスクを持つネットワーク 10.0.0.1 として表すことができます。特定の IP アドレスがこのネットワークと一致するかどうかを確認するには、マスクを IP アドレスに適用し、それをネットワーク アドレスと比較します。それらが一致する場合、アドレスはネットワーク内にあります。たとえば、10.0.4.1 をテストする場合は、ビットごとの AND を使用してマスクを適用します。

10.0.4.1 & 255.255.0.255 = 10.0.0.1

これはネットワーク アドレスと一致するため、この IP はネットワーク内にあります。

このネットワークを次のようにテーブルに保存できます (ip と mask は整数です)。

CREATE TABLE networks (id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, ip INT, mask INT);

INSERT INTO networks (ip, mask)
VALUES (INET_ATON('10.0.0.1'), INET_ATON('255.255.0.255'));

特定の IP (10.0.23.1) が次のように一致するかどうかを確認できます。

SELECT * FROM networks
WHERE ip & mask = INET_ATON('10.0.23.1') & mask

ただし、人間が判読できるようにする場合は、これにより 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

これにより、特定の 1 つの IP アドレスがネットワークと一致するかどうかをテストできます。IP の範囲をテストする場合は、範囲内の各 IP にマスクを適用し、上記のようにそれぞれをテストする必要があります。単一のクエリで実行できます。テストするすべての IP アドレスをリストするだけです。

于 2012-10-01T12:11:19.640 に答える
2

次のように、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')

それは仕事を成し遂げる少し冗長なビットです。

通常の IP フィールドからその構造を使用して一時テーブルを作成することも可能ですが、多くのリクエストがある場合はオーバーヘッドが大きくなります。

于 2012-10-01T12:08:25.330 に答える
0

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;

さて、あなたはこれを行うことができます:

WHERE ipField LIKE '10.0.%.1'
AND (CAST
       (REPLACE(SUBSTRING_INDEX(ipField,'.',3),
                CONCAT(SUBSTRING_INDEX(ipField ,'.',2),'.')
                ,'')
     AS UNSIGNED) BETWEEN 0 AND 255) 

次のクエリでテストしました:

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 文字列関数 (ほとんどの場合、記述するのが面倒になります) の詳細については、こちらのドキュメントを参照してください。

于 2012-10-01T12:19:05.633 に答える