sql >> データベース >  >> RDS >> Mysql

ip =inet_pton($ ip)の場所を選択できません

    まず、修正方法は非常に簡単です。IPv4アドレスとIPv6アドレスの両方を保存する場合は、VARBINARY(16)を使用する必要があります。 BINARY(16)の代わりに 。

    ここで問題が発生します。BINARY(16)で期待どおりに機能しないのはなぜですか。 ?

    テーブルipsがあるとします。 1列のみip BINARY(16) PRIMARY KEY 。デフォルトのローカルIPv4アドレスを

    で保存します
    $stmt = $db->prepare("INSERT INTO ips(ip) VALUES(?)");
    $stmt->execute([inet_pton('127.0.0.1')]);
    

    データベースで次の値を見つけます。

    0x7F000001000000000000000000000000
    

    ご覧のとおり、これは4バイトのバイナリ値です(0x7F000001 )16バイトの固定長列に合うようにゼロが右に埋め込まれます。

    あなたが今それを見つけようとするとき

    $stmt = $db->prepare("SELECT * FROM ips WHERE ip = ?");
    $stmt->execute([inet_pton('127.0.0.1')]);
    

    次のようになります。PHPは値0x7F000001を送信します 保存された値0x7F000001000000000000000000000000と比較されるパラメータとして ただし、長さが異なる2つのバイナリ値が等しくなることはないため、WHERE条件は常にFALSEを返します。

    で試すことができます。
    SELECT 0x00 = 0x0000
    

    0を返します (FALSE)。

    注:固定長の非バイナリ文字列(CHAR(N)では、動作が異なります。 。

    回避策として明示的なキャストを使用できます:

    $stmt = $db->prepare("SELECT * FROM ips WHERE ip = CAST(? as BINARY(16))");
    $stmt->execute([inet_pton('127.0.0.1')]);
    

    そしてそれは行を見つけます。しかし、私たちが得たものを見ると

    var_dump(inet_ntop($stmt->fetch(PDO::FETCH_OBJ)->ip));
    

    表示されます

    string(8) "7f00:1::"
    

    しかし、それは(実際には)私たちが保存しようとしたものではありません。そして今、7f00:1::を保存しようとすると 、重複キーエラーが発生します 、IPv6アドレスはまだ保存していませんが。

    もう一度:VARBINARY(16)を使用します 、コードをそのままにしておくことができます。多くのIPv4アドレスを保存すると、ストレージを節約することもできます。



    1. PostgresでのLIKEと〜の違い

    2. SQLiteStatementはSELECT/INSERT / DELETE/UPDATEを実行します

    3. MOOCプラットフォームのデータベースモデル

    4. php、mysql-データベースへの接続が多すぎますエラー