SQL ServerにIPアドレスを格納するためのデータ型


113

SQL ServerにIPアドレスを格納するためにどのデータ型を選択する必要がありますか?

適切なデータ型を選択することで、IPアドレスでフィルタリングするのは簡単でしょうか?



回答:


130

IPv4を格納する技術的に正しい方法は、binary(4)です。これは、実際にそれがそうであるからです(いいえ、INT32 / INT(4)でさえありません。バイナリコンテンツの表示変換)。

このようにすると、テキスト表示形式との間で変換する関数が必要になります。

テキスト表示形式をバイナリに変換する方法は次のとおりです。

CREATE FUNCTION dbo.fnBinaryIPv4(@ip AS VARCHAR(15)) RETURNS BINARY(4)
AS
BEGIN
    DECLARE @bin AS BINARY(4)

    SELECT @bin = CAST( CAST( PARSENAME( @ip, 4 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 3 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 2 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 1 ) AS INTEGER) AS BINARY(1))

    RETURN @bin
END
go

バイナリを変換してテキスト表示形式に戻す方法は次のとおりです。

CREATE FUNCTION dbo.fnDisplayIPv4(@ip AS BINARY(4)) RETURNS VARCHAR(15)
AS
BEGIN
    DECLARE @str AS VARCHAR(15) 

    SELECT @str = CAST( CAST( SUBSTRING( @ip, 1, 1) AS INTEGER) AS VARCHAR(3) ) + '.'
                + CAST( CAST( SUBSTRING( @ip, 2, 1) AS INTEGER) AS VARCHAR(3) ) + '.'
                + CAST( CAST( SUBSTRING( @ip, 3, 1) AS INTEGER) AS VARCHAR(3) ) + '.'
                + CAST( CAST( SUBSTRING( @ip, 4, 1) AS INTEGER) AS VARCHAR(3) );

    RETURN @str
END;
go

これらの使用方法のデモを次に示します。

SELECT dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go

SELECT dbo.fnDisplayIPv4( 0xC04144C9 )
-- should return '192.65.68.201'
go

最後に、ルックアップと比較を行うときに、インデックスを活用できるようにする場合は、常にバイナリ形式を使用します。


更新:

SQL ServerのスカラーUDFに固有のパフォーマンスの問題に対処する方法を1つ追加したいと思いますが、関数のコード再利用を維持するには、代わりにiTVF(インラインテーブル値関数)を使用します。上記の最初の関数(文字列からバイナリへ)をiTVFとして書き直す方法は次のとおりです。

CREATE FUNCTION dbo.itvfBinaryIPv4(@ip AS VARCHAR(15)) RETURNS TABLE
AS RETURN (
    SELECT CAST(
               CAST( CAST( PARSENAME( @ip, 4 ) AS INTEGER) AS BINARY(1))
            +  CAST( CAST( PARSENAME( @ip, 3 ) AS INTEGER) AS BINARY(1))
            +  CAST( CAST( PARSENAME( @ip, 2 ) AS INTEGER) AS BINARY(1))
            +  CAST( CAST( PARSENAME( @ip, 1 ) AS INTEGER) AS BINARY(1))
                AS BINARY(4)) As bin
        )
go

これが例です:

SELECT bin FROM dbo.fnBinaryIPv4('192.65.68.201')
--should return 0xC04144C9
go

そして、これがINSERTでそれをどのように使用するかです

INSERT INTo myIpTable
SELECT {other_column_values,...},
       (SELECT bin FROM dbo.itvfBinaryIPv4('192.65.68.201'))

33
これは学問的な意味でのみ正しいと思います。投稿者が解決しようとしている目的とドメインの問題を知らなければ、データとのやり取りが不必要に複雑になり、パフォーマンスが低下する可能性があると思います。
Eric Sabine

21
IPv4は、4バイトの順序付けられたシーケンスです。これは、ISそれのドメイン、およびBIN(4)のストレージ形式です。ストレージ形式は最適な形式であるため、パフォーマンスを妨げることはありません。変換関数は(UDFがSQLサーバーを吸うため)可能性があり、インライン化するか、クライアントで変換することによって解決できます。最後に、このアプローチは、索引付けされたレンジ・スキャンを使用して、クラス1,2、又は3つのサブネットワークのアドレスを検索することができることは重要な利点を有している(ここで、IP fnBinaryIPv4(「132.31.55.00」)AND fnBinaryIPv4(BETWEEN「132.31.55.255」))
RBarryYoung 2009

1
@RBarryYoung整数として保存します。バイナリとして保存することのパフォーマンス上の利点は何ですか?
Pacerier、2011年

3
@Pacerier:1)例については前のコメントを参照してください。2)BinaryがIntegerよりも速いとは主張していません。私は、A)それは正しいフォーマット(そしてそれが正しい)であり、B)遅くなることはないと主張しました。
RBarryYoung、2011年

1
はい、あなたは間違っています、それはダンが言っていることではありません。また、これはディスカッションフォーラムではないため、適していません。StackoverflowはQ&Aのフロムです。質問がある場合は投稿してください。
RBarryYoung 2011年

23

varcharを使用できます。IPv4の長さは静的ですが、IPv6の長さは非常に変動する可能性があります。

バイナリとして保存する十分な理由がない限り、文字列(テキスト)タイプのままにします。


39
IPv6の長さは非常に固定されています-128ビット。
Broam

4
人間が決して読まないデータや大量のデータについて話しているのでなければ、これが最良の答えです。
Aren Cambre 2014年

10
文字列ではなくバイナリを使用する1つの単純な理由:バイナリバージョンでは、IPアドレスの数値範囲チェックが可能です。テキスト版にはありません。もちろん、これは必要な用途によって異なりますが、2進数は実際の意味を持つため、より便利です。
コーディング終了

4
varcharは、DBで大幅に多くのスペースを使用します。32ビットのIPv4アドレスは、数値を格納するために4バイトを使用し、128ビットのIPv6アドレスは、数値を格納するために16バイトを使用します。その間、そのIPv4アドレスは文字列として格納するために15バイトかかり、IPv6アドレスは文字列として最大39バイトを取る可能性があります。
アーロンシュルツ

1
varbinary(16)を使用する方法
jjxtra 2018

17

次に、varchar形式のIPV4またはIPv6のいずれかをbinary(16)に変換して戻すコードを示します。これは私が考えることができる最小の形です。インデックスを適切に作成し、サブネットでフィルタリングする比較的簡単な方法を提供する必要があります。SQL Server 2005以降が必要です。完全に防弾であるかどうかはわかりません。お役に立てれば。

-- SELECT dbo.fn_ConvertIpAddressToBinary('2002:1ff:6c2::1ff:6c2')
-- SELECT dbo.fn_ConvertIpAddressToBinary('10.4.46.2')
-- SELECT dbo.fn_ConvertIpAddressToBinary('bogus')

ALTER FUNCTION dbo.fn_ConvertIpAddressToBinary
(
     @ipAddress VARCHAR(39)
)
RETURNS BINARY(16) AS
BEGIN
DECLARE
     @bytes BINARY(16), @vbytes VARBINARY(16), @vbzone VARBINARY(2)
     , @colIndex TINYINT, @prevColIndex TINYINT, @parts TINYINT, @limit TINYINT
     , @delim CHAR(1), @token VARCHAR(4), @zone VARCHAR(4)

SELECT
     @delim = '.'
     , @prevColIndex = 0
     , @limit = 4
     , @vbytes = 0x
     , @parts = 0
     , @colIndex = CHARINDEX(@delim, @ipAddress)

IF @colIndex = 0
     BEGIN
           SELECT
                @delim = ':'
                , @limit = 8
                , @colIndex = CHARINDEX(@delim, @ipAddress)
           WHILE @colIndex > 0
                SELECT
                      @parts = @parts + 1
                      , @colIndex = CHARINDEX(@delim, @ipAddress, @colIndex + 1)
           SET @colIndex = CHARINDEX(@delim, @ipAddress)

           IF @colIndex = 0
                RETURN NULL     
     END

SET @ipAddress = @ipAddress + @delim

WHILE @colIndex > 0
     BEGIN
           SET @token = SUBSTRING(@ipAddress, @prevColIndex + 1, @Colindex - @prevColIndex - 1)

           IF @delim = ':'
                BEGIN
                      SET  @zone = RIGHT('0000' + @token, 4)

                      SELECT
                           @vbzone = CAST('' AS XML).value('xs:hexBinary(sql:variable("@zone"))', 'varbinary(2)')
                           , @vbytes = @vbytes + @vbzone

                      IF @token = ''
                           WHILE @parts + 1 < @limit
                                 SELECT
                                      @vbytes = @vbytes + @vbzone
                                      , @parts = @parts + 1
                END
           ELSE
                BEGIN
                      SET @zone = SUBSTRING('' + master.sys.fn_varbintohexstr(CAST(@token AS TINYINT)), 3, 2)

                      SELECT
                           @vbzone = CAST('' AS XML).value('xs:hexBinary(sql:variable("@zone"))', 'varbinary(1)')
                           , @vbytes = @vbytes + @vbzone
                END

           SELECT
                @prevColIndex = @colIndex
                , @colIndex = CHARINDEX(@delim, @ipAddress, @colIndex + 1) 
     END            

SET @bytes =
     CASE @delim
           WHEN ':' THEN @vbytes
           ELSE 0x000000000000000000000000 + @vbytes
     END 

RETURN @bytes

END
-- SELECT dbo.fn_ConvertBinaryToIpAddress(0x200201FF06C200000000000001FF06C2)
-- SELECT dbo.fn_ConvertBinaryToIpAddress(0x0000000000000000000000000A0118FF)

ALTER FUNCTION [dbo].[fn_ConvertBinaryToIpAddress]
(
     @bytes BINARY(16)
)
RETURNS VARCHAR(39) AS
BEGIN
DECLARE
     @part VARBINARY(2)
     , @colIndex TINYINT
     , @ipAddress VARCHAR(39)

SET @ipAddress = ''

IF SUBSTRING(@bytes, 1, 12) = 0x000000000000000000000000
     BEGIN
           SET @colIndex = 13
           WHILE @colIndex <= 16
                SELECT
                      @part = SUBSTRING(@bytes, @colIndex, 1)
                      , @ipAddress = @ipAddress
                           + CAST(CAST(@part AS TINYINT) AS VARCHAR(3))
                           + CASE @colIndex WHEN 16 THEN '' ELSE '.' END
                      , @colIndex = @colIndex + 1

           IF @ipAddress = '0.0.0.1'
                SET @ipAddress = '::1'
     END
ELSE
     BEGIN
           SET @colIndex = 1
           WHILE @colIndex <= 16
                BEGIN
                      SET @part = SUBSTRING(@bytes, @colIndex, 2)
                      SELECT
                           @ipAddress = @ipAddress
                                 + CAST('' as xml).value('xs:hexBinary(sql:variable("@part") )', 'varchar(4)')
                                 + CASE @colIndex WHEN 15 THEN '' ELSE ':' END
                           , @colIndex = @colIndex + 2
                END
     END

RETURN @ipAddress   

END 

この回答は、db-ip IP to countryデータベースでは問題なく機能しました。往復変換では、0がipv6(先行および後続)から削除されたわずかな違いのみが示されました。
crokusek 2016年

1
ToBinary()で、クエリプランと、確定的とマークされていないfn_varbintohexstr()の使用に関する問題に遭遇しました。else '。'はどうですか?セクション:select @ vbzone = convert(varbinary(2)、convert(tinyint、@ token))?同等のようです。@ゾーンやxmlエンジンは必要ありませんか?XMLエンジンが ':'からもどういうわけか削除した場合、速度が向上したように見えます。
crokusek 2016年

concat_ws( '。'、(IPAddr&0xFF000000)>> 24、(IPAddr&0xFF0000)>> 16、(IPAddr&0xFF00)>> 8、(IPAddr&0xFF))は、IPアドレスを含むunsigned longをaに変換します人間が読める形式。
theking2

@ theking2->>はサポートされていないため、SQL Serverには適用されません
Alex

にはバグがあることに注意してくださいfn_ConvertIpAddressToBinaryC.Plockの回答と記事を参照してください。
Alex

10

私は両方を処理するようIPv4IPv6、私が使用していますVARBINARY(16)以下とSQL CLR変換するための関数をtextバイトにIPアドレスプレゼンテーションとは逆に:

[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
public static SqlBytes GetIPAddressBytesFromString (SqlString value)
{
    IPAddress IP;

    if (IPAddress.TryParse(value.Value, out IP))
    {
        return new SqlBytes(IP.GetAddressBytes());
    }
    else
    {
        return new SqlBytes();
    }
}


[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
public static SqlString GetIPAddressStringFromBytes(SqlBytes value)
{
    string output;

    if (value.IsNull)
    {
        output = "";
    }
    else
    {
        IPAddress IP = new IPAddress(value.Value);
        output = IP.ToString();
    }

    return new SqlString(output);
}

8

.NETを使用している人は、IPAddressクラスを使用してIPv4 / IPv6文字列を解析し、それをとして保存できますVARBINARY(16)。同じクラスを使用byte[]して文字列に変換できます。VARBINARYSQLで変換したい場合:

--SELECT 
--  dbo.varbinaryToIpString(CAST(0x7F000001 AS VARBINARY(4))) IPv4,
--  dbo.varbinaryToIpString(CAST(0x20010DB885A3000000008A2E03707334 AS VARBINARY(16))) IPv6

--ALTER 
CREATE
FUNCTION dbo.varbinaryToIpString
(
    @varbinaryValue VARBINARY(16)
)
RETURNS VARCHAR(39)
AS
BEGIN
    IF @varbinaryValue IS NULL
        RETURN NULL
    IF DATALENGTH(@varbinaryValue) = 4
    BEGIN
        RETURN 
            CONVERT(VARCHAR(3), CONVERT(INT, SUBSTRING(@varbinaryValue, 1, 1))) + '.' +
            CONVERT(VARCHAR(3), CONVERT(INT, SUBSTRING(@varbinaryValue, 2, 1))) + '.' +
            CONVERT(VARCHAR(3), CONVERT(INT, SUBSTRING(@varbinaryValue, 3, 1))) + '.' +
            CONVERT(VARCHAR(3), CONVERT(INT, SUBSTRING(@varbinaryValue, 4, 1)))
    END
    IF DATALENGTH(@varbinaryValue) = 16
    BEGIN
        RETURN 
            sys.fn_varbintohexsubstring(0, @varbinaryValue,  1, 2) + ':' +
            sys.fn_varbintohexsubstring(0, @varbinaryValue,  3, 2) + ':' +
            sys.fn_varbintohexsubstring(0, @varbinaryValue,  5, 2) + ':' +
            sys.fn_varbintohexsubstring(0, @varbinaryValue,  7, 2) + ':' +
            sys.fn_varbintohexsubstring(0, @varbinaryValue,  9, 2) + ':' +
            sys.fn_varbintohexsubstring(0, @varbinaryValue, 11, 2) + ':' +
            sys.fn_varbintohexsubstring(0, @varbinaryValue, 13, 2) + ':' +
            sys.fn_varbintohexsubstring(0, @varbinaryValue, 15, 2)
    END

    RETURN 'Invalid'
END

7

sys.dm_exec_connectionsSQL Server 2005 SP1の後でvarchar(48)を使用します。特にあなたがそれをあなたの価値と比較して使いたいなら、私には十分に聞こえます。

現実的には、しばらくの間IPv6が主流になるとは思わないので、4 tinyintルートを使用します。それを言って、私は使用する必要があるため、varchar(48)を使用していますsys.dm_exec_connectionsます...

さもないと。Mark Redmanの回答は、以前のSOの議論の質問に言及しています。


4
現実的に、IPv6が表示されます
Pacerier '15年

10
現実的には2000年はしばらく表示されません。2桁の日付を使用して数バイトを節約することもできます。あ、ちょっと待って。
エリックJ.

1

RBarryに感謝します。私はIPブロック割り当てシステムをまとめて、バイナリとして保存するのが唯一の方法です。

IPブロックのCIDR表現(例:192.168.1.0/24)をvarcharフィールドに格納し、2つの計算フィールドを使用して、ブロックの開始と終了のバイナリ形式を保持しています。そこから、高速クエリを実行して、特定のブロックが既に割り当てられているか、割り当てが自由かを確認できます。

関数を変更して、次のように終了IPアドレスを計算しました。

CREATE FUNCTION dbo.fnDisplayIPv4End(@block AS VARCHAR(18)) RETURNS BINARY(4)
AS
BEGIN
    DECLARE @bin AS BINARY(4)
    DECLARE @ip AS VARCHAR(15)
    DECLARE @size AS INT

    SELECT @ip = Left(@block, Len(@block)-3)
    SELECT @size = Right(@block, 2)

    SELECT @bin = CAST( CAST( PARSENAME( @ip, 4 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 3 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 2 ) AS INTEGER) AS BINARY(1))
                + CAST( CAST( PARSENAME( @ip, 1 ) AS INTEGER) AS BINARY(1))

    SELECT @bin = CAST(@bin + POWER(2, 32-@size) AS BINARY(4))
    RETURN @bin
END;
go

1

私は通常、IPAddressに対してプレーンな古いVARCHARフィルタリングを使用して正常に機能します。

IPアドレスの範囲でフィルタリングする場合は、4つの整数に分割します。


1
範囲とは何ですか?すべてのサブネットが8バイトであるとは限りません。このホストが存在するネットワークのIPアドレスの範囲は50.50.50.50/20ですか?
Bradley Kreider 2011

2
整数は大きすぎて0〜255の値を格納できません。代わりにtinyintを使用してください。
SandRock、2015年

0

サンドロックの機能が好きです。しかし、dbo.fn_ConvertIpAddressToBinaryのコードにエラーが見つかりました。@delimを連結すると、@ ipAddress VARCHAR(39)の受信パラメーターが小さすぎます。

SET @ipAddress = @ipAddress + @delim

あなたはそれを40に増やすことができます。または、より良いまだより大きな新しい変数を使用し、それを内部的に使用します。そうすれば、多数の最後のペアを失うことはありません。

SELECT dbo.fn_ConvertIpAddressToBinary('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')

確かにバグがあります
Alex

0

次の回答は、この質問に対するM. TurnhoutJerry Birchlerの回答に基づいていますが、次の点が改善されています。

  • ドキュメント化されていない関数(sys.fn_varbintohexsubstringfn_varbintohexstr)の使用CONVERT()バイナリスタイルに置き換え
  • 置き換えXML「ハック」(CAST('' as xml).value('xs:hexBinary())と)CONVERT()のためのバイナリのスタイル
  • Jerry Birchlerの実装のバグを修正fn_ConvertIpAddressToBinaryC.Plockで指摘)
  • マイナーな構文シュガーを追加

コードはSQL Server 2014およびSQL Server 2016でテストされています(最後のテストケースを参照)

IPAddressVarbinaryToString

4バイト値をIPV4に、16バイト値をIPV6文字列表現に変換します。この関数はアドレスを短縮しないことに注意してください。

ALTER FUNCTION dbo.IPAddressVarbinaryToString
(
    @varbinaryValue VARBINARY( 16 )
)
RETURNS VARCHAR(39)
AS
BEGIN
    IF @varbinaryValue IS NULL
        RETURN NULL;
    ELSE IF DATALENGTH( @varbinaryValue ) = 4
        RETURN 
            CONVERT( VARCHAR(3), CONVERT(TINYINT, SUBSTRING( @varbinaryValue, 1, 1 ))) + '.' +
            CONVERT( VARCHAR(3), CONVERT(TINYINT, SUBSTRING( @varbinaryValue, 2, 1 ))) + '.' +
            CONVERT( VARCHAR(3), CONVERT(TINYINT, SUBSTRING( @varbinaryValue, 3, 1 ))) + '.' +
            CONVERT( VARCHAR(3), CONVERT(TINYINT, SUBSTRING( @varbinaryValue, 4, 1 )));
    ELSE IF DATALENGTH( @varbinaryValue ) = 16
        RETURN 
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue,  1, 2 ), 2 ) + ':' +
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue,  3, 2 ), 2 ) + ':' +
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue,  5, 2 ), 2 ) + ':' +
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue,  7, 2 ), 2 ) + ':' +
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue,  9, 2 ), 2 ) + ':' +
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue, 11, 2 ), 2 ) + ':' +
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue, 13, 2 ), 2 ) + ':' +
            CONVERT( VARCHAR(4), SUBSTRING( @varbinaryValue, 15, 2 ), 2 );

    RETURN 'Invalid';
END

テストケース:

SELECT dbo.IPAddressVarbinaryToString(0x00000000000000000000000000000000) -- 0000:0000:0000:0000:0000:0000:0000:0000 (no address shortening)
SELECT dbo.IPAddressVarbinaryToString(0x00010002000300400500060070000089) -- 0001:0002:0003:0040:0500:0600:7000:0089
SELECT dbo.IPAddressVarbinaryToString(0xC0A80148) -- 255.168.1.72
SELECT dbo.IPAddressVarbinaryToString(0x7F000001) -- 127.0.0.1 (no address shortening)
SELECT dbo.IPAddressVarbinaryToString(NULL) -- NULL

IPAddressStringToVarbinary

IPV4およびIPV6文字列表現を、それぞれ4バイトおよび16バイトのバイナリ値に変換します。この関数は、ほとんどの(すべての一般的に使用される)省略アドレス表現(例:127 ... 1および2001:db8 :: 1319:370:7348)を解析できることに注意してください。関数thinsが常に16バイトのバイナリ値を返すようにするには、関数の最後にある先行0の連結をコメント解除します。

ALTER FUNCTION [dbo].[IPAddressStringToVarbinary]
(
    @IPAddress VARCHAR( 39 )
)
RETURNS VARBINARY(16) AS
BEGIN

IF @ipAddress IS NULL
    RETURN NULL;

DECLARE @bytes VARBINARY(16), @token VARCHAR(4),
    @vbytes VARBINARY(16) = 0x, @vbzone VARBINARY(2),
    @tIPAddress VARCHAR( 40 ),
    @colIndex TINYINT,
    @delim CHAR(1) = '.',
    @prevColIndex TINYINT = 0,
    @parts TINYINT = 0, @limit TINYINT = 4;

-- Get position if IPV4 delimiter
SET @colIndex = CHARINDEX( @delim, @ipAddress );

-- If not IPV4, then assume IPV6
IF @colIndex = 0
BEGIN
    SELECT @delim = ':', @limit = 8, @colIndex = CHARINDEX( @delim, @ipAddress );

    -- Get number of parts (delimiters)
    WHILE @colIndex > 0
        SELECT @parts += 1, @colIndex = CHARINDEX( @delim, @ipAddress, @colIndex + 1 );

    SET @colIndex = CHARINDEX( @delim, @ipAddress );

    IF @colIndex = 0
        RETURN NULL;
END

-- Add trailing delimiter (need new variable of larger size)
SET @tIPAddress = @IPAddress + @delim;

WHILE @colIndex > 0
BEGIN
    SET @token = SUBSTRING( @tIPAddress, @prevColIndex + 1, @Colindex - @prevColIndex - 1 );

    IF @delim = ':'
    BEGIN
        SELECT @vbzone = CONVERT( VARBINARY(2), RIGHT( '0000' + @token, 4 ), 2 ), @vbytes += @vbzone;

        -- Handles consecutive sections of zeros representation rule (i.e. ::)(https://en.wikipedia.org/wiki/IPv6#Address_representation)
        IF @token = ''
            WHILE @parts + 1 < @limit
                SELECT @vbytes += @vbzone, @parts += 1;
    END
    ELSE
    BEGIN
        SELECT @vbzone = CONVERT( VARBINARY(1), CONVERT( TINYINT, @token )), @vbytes += @vbzone
    END

    SELECT @prevColIndex = @colIndex, @colIndex = CHARINDEX( @delim, @tIPAddress, @colIndex + 1 ) 
END

SET @bytes =
    CASE @delim
        WHEN ':' THEN @vbytes
        ELSE /*0x000000000000000000000000 +*/ @vbytes -- Return IPV4 addresses as 4 byte binary (uncomment leading 0s section to force 16 byte binary)
    END 

RETURN @bytes

END

テストケース

有効なケース

SELECT dbo.IPAddressStringToVarbinary( '0000:0000:0000:0000:0000:0000:0000:0001' ) -- 0x0000000000000000000000000001 (check bug fix)
SELECT dbo.IPAddressStringToVarbinary( '0001:0002:0003:0040:0500:0600:7000:0089' ) -- 0x00010002000300400500060070000089
SELECT dbo.IPAddressStringToVarbinary( '2001:db8:85a3:8d3:1319::370:7348' )     -- 0x20010DB885A308D31319000003707348 (check short hand)
SELECT dbo.IPAddressStringToVarbinary( '2001:db8:85a3:8d3:1319:0000:370:7348' ) -- 0x20010DB885A308D31319000003707348
SELECT dbo.IPAddressStringToVarbinary( '192.168.1.72' ) -- 0xC0A80148
SELECT dbo.IPAddressStringToVarbinary( '127...1' ) -- 0x7F000001 (check short hand)
SELECT dbo.IPAddressStringToVarbinary( NULL ) -- NULL
SELECT dbo.IPAddressStringToVarbinary( '' ) -- NULL
-- Check that conversions return original address
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '0001:0002:0003:0040:0500:0600:7000:0089' )) -- '0001:0002:0003:0040:0500:0600:7000:0089' 
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '127...1' )) -- 127.0.0.1
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '192.168.1.72' )) -- 192.168.1.72
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '2001:db8:85a3:8d3:1319::370:7348' ))     -- 2001:0db8:85a3:08d3:1319:0000:0370:7348
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '2001:db8:85a3:8d3:1314:0000:370:7348' )) -- 2001:0db8:85a3:08d3:1319:0000:0370:7348
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '2001:db8:85a3:8d3::370:7348' )) -- 2001:0DB8:85A3:08D3:0000:0000:0370:7348
-- This is technically an invalid IPV6 (according to Wikipedia) but it parses correctly
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '2001:db8::1319::370:7348' )) -- 2001:0DB8:0000:0000:1319:0000:0370:7348

無効なケース

SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '2001:db8::1319::7348' )) -- 2001:0DB8:0000:0000:0000:1319:0000:7348 (ambiguous address)
SELECT dbo.IPAddressStringToVarbinary( '127.1' ) -- 127.0.0.1 (not supported short-hand)
SELECT dbo.IPAddressVarbinaryToString( dbo.IPAddressStringToVarbinary( '127.1' )) -- 127.0.0.1 (not supported short-hand)
SELECT dbo.IPAddressStringToVarbinary( '0300.0000.0002.0353' ) -- octal byte values
SELECT dbo.IPAddressStringToVarbinary( '0xC0.0x00.0x02.0xEB' ) -- hex values
SELECT dbo.IPAddressStringToVarbinary( 'C0.00.02.EB' ) -- hex values

-2

私は使っています varchar(15)これまでのところ、すべてが私のために働いています。挿入、更新、選択。IPアドレスを含むアプリを開始したばかりですが、まだ開発作業はあまり行っていません。

以下は、selectステートメントです。

select * From dbo.Server 
where  [IP] = ('132.46.151.181')
Go
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.