亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用于在SQL Server中存儲ip地址的數據類型

用于在SQL Server中存儲ip地址的數據類型

慕俠2389804 2019-08-30 16:53:19
我應該選擇什么數據類型在SQL Server中存儲IP地址?通過選擇正確的數據類型,可以很容易地按IP地址進行過濾嗎?
查看完整描述

3 回答

?
慕尼黑8549860

TA貢獻1818條經驗 獲得超11個贊

存儲IPv4的技術上正確的方法是二進制(4),因為它實際上是它(不,甚至不是INT32 / INT(4),我們都知道和喜歡的數字文本形式(255.255.255.255)只是其二進制內容的顯示轉換)。


如果你這樣做,你會希望函數轉換為文本顯示格式:


以下是將文本顯示形式轉換為二進制的方法:


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的固有性能問題,但仍然保留函數的代碼重用是使用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'))


查看完整回答
反對 回復 2019-08-30
?
陪伴而非守候

TA貢獻1757條經驗 獲得超8個贊

以下是將varchar格式的IPV4或IPv6轉換為二進制(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 


查看完整回答
反對 回復 2019-08-30
  • 3 回答
  • 0 關注
  • 1018 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號