2012-10-01 9 views
5

10.0%などのワイルドカードを使用してIPアドレスを格納する必要があります。次に、私の質問から許可された範囲(10.0.0-255.1)のIPアドレスを持つ人が見つかります。MySQLでワイルドカードを使用して文字列を保存(および検索)するにはどうすればよいですか?

あなたは私を助けてくれますか?私は10.0%。1を保存しようとしましたが、LIKEクエリではそれを見つけることができません。

ありがとうございます。

あなたについてそうのような、データベース内の4つの整数としてIPアドレスを保存する方法
+0

なぜ値を%で保存しますか? –

+0

255より大きい数値( '350'など)を使用し、phpのワイルドカードで置き換えますか? – hjpotter92

+0

ワイルドカードはどのように使いたいですか? 10.0.1%と0.1%も有効と考えられますか? – Josay

答えて

2

IPpart1 IPpart2 IPpart3 IPpart4 
------------------------------- 
127  0  0  1 

し、それらをNULL可能にします。

あなたは、このようなDBにクエリを行うことができます(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フィールドからその構造を持つテンポラリテーブルを構築することは可能ですが、多くのリクエストがあるとオーバーヘッドが大きくなります。

+0

異なるアプローチをお寄せいただきありがとうございます。 –

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はネットワークです。

SELECT * FROM networks 
WHERE ip & mask = INET_ATON('10.0.23.1') & mask 
:指定したIP(10.0.23.1)は次のように一致した場合は、見つけることができます

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とマスクは整数)のように、あなたのテーブルにこのネットワークを保存することができます

これは、あなたがそれらを人間が読めるたい場合は、しかし整数として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 

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

+0

興味深いことに、このようなIPの範囲を照会することは可能でしょうか? 'BETWEEN int1 AND int2'を使用する場合、' 10.0.12.1'から '10.0.123.2'までの範囲ですか? –

+0

いいえ、あなたはできません。範囲内の各IPアドレスにマスクを適用し、それをネットワークアドレスと比較する必要があります。これは、ネットワークマスクに穴がある可能性があり、範囲の両端がネットワーク内にあっても、範囲の中央にあるいくつかのアドレスがネットワークにない可能性があるからです。たとえば、私のマスクが10.0.0.1ネットワークで255.255.2.255だった場合、IP 10.0.0.1,10.0.4.1および10.0.5.1はネットワーク上にありますが、10.0.2.1および10.0.3.1はそうではありません。 –

+0

INET_ATOM('10 .0.20.1 ')&maskとINET_ATOM('10 .0.50.1')&mask 'の間にはどこのIP&マスクが使えませんか?最悪の場合、あなたは一種の参加が必要ですが、私が何かが欠けていなければ、それはうまくいくでしょうか? –

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

そして、それは正直、それはfaffの少しだ、1返しますが、ではなく、それ?なぜ単純ではない:

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

あなたはこの表現を少し微調整することができますが、基本的に、それは、それらのIPアドレスを照会する最も簡単な方法であると私には思えます。
MySQLの文字列関数の詳細については、ほとんど常に苦労しています。the docs here

+0

これらの 'SUBSTRING_INDEX()'関数を使って文字列IPを整数に変換するのではなく、 'INET_ATON()'だけを使うことができます。 –

+0

私はこれを投稿した後、あなたの答えを読んで投票しました - あなたの答えを実装するのが彼のテーブルを変更する必要があるかもしれないとOPが疑問を抱いていて、IPの範囲を問い合わせるのに 'BETWEEN 'それを反映するためにあなたの答えを編集したいかもしれません。 IMO、あなたの答えですが、私はここでいくつかのpplに使用するかもしれないいくつかのリンクを与えましたが、私は再び言います:手元の質問に最も良い答えを提供しました –

+0

ありがとう、テーブルスキーマとIPの範囲のテスト –

関連する問題