SQL सर्वर में IP पते को संग्रहीत करने के लिए डेटाटाइप


113

SQL सर्वर में IP एड्रेस को संग्रहीत करने के लिए मुझे क्या डेटाटाइप चुनना चाहिए?

सही डेटाटाइप का चयन करके आईपी पते से फ़िल्टर करना काफी आसान होगा?


इस उत्तर पर एक नज़र डालें: stackoverflow.com/questions/1038950/…
मार्क रेडमैन

जवाबों:


130

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 सर्वर में स्केलर UDFs की अंतर्निहित प्रदर्शन समस्याओं को दूर करने के लिए उस तरीके को जोड़ना चाहता था, लेकिन फिर भी एक फ़ंक्शन का कोड-पुन: उपयोग बनाए रखना है इसके बजाय एक 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
मुझे लगता है कि यह केवल अकादमिक अर्थों में सही है। उद्देश्य और डोमेन समस्या को जाने बिना, जिसके लिए पोस्टर मुझे संदेह करने की कोशिश कर रहा है यह अनावश्यक रूप से डेटा और संभावित रूप से प्रदर्शन में गिरावट के साथ बातचीत को जटिल करेगा।
एरिक सबाइन

21
IPv4 चार बाइट्स का एक क्रमबद्ध क्रम है। यह एक डोमेन है, और एक BIN (4) है कि भंडारण प्रारूप में है। भंडारण प्रारूप प्रदर्शन में हस्तक्षेप नहीं करेगा क्योंकि यह इष्टतम प्रारूप है। रूपांतरण फ़ंक्शन (क्योंकि SQL सर्वर पर यूडीएफ का चूसना) हो सकता है, जिसे क्लाइंट में रूपांतरण को इन-लाइनिंग या हल करके हल किया जा सकता है। अंत में, इस दृष्टिकोण का महत्वपूर्ण लाभ है कि यह अनुक्रमित श्रेणी स्कैन (WHERE ip BETWEEN fnBinaryIPv4 ('132.31.55.00') और fbBinaryIPv4 ('132.31.55.255')) का उपयोग करके कक्षा 1,2, या 3 सबनेटवर्क में पते खोज सकते हैं
RBarryYoung

1
@RBryryYoung मैं इसे पूर्णांक के रूप में संग्रहीत करूंगा। क्या आप बता सकते हैं कि इसे बाइनरी के रूप में संग्रहीत करने का प्रदर्शन लाभ क्या है?
पेसियर

3
@Pacerier: 1) पिछली टिप्पणी को एक उदाहरण के लिए देखें, और 2) मैंने यह दावा नहीं किया कि बाइनरी इंटेगर की तुलना में तेज़ होगी। मैंने दावा किया कि ए) यह सही प्रारूप है (और यह है), और बी) यह धीमा नहीं होगा।
RBarryYoung

1
हां, आप गलत हैं, ऐसा दान नहीं कह रहा है। इसके अलावा, यह एक चर्चा मंच नहीं है, और यह इसके लिए अनुकूल नहीं है। Stackoverflow एक Q & A froum है, अगर आपका कोई सवाल है तो कृपया इसे पोस्ट करें।
RBarryYoung

23

आप varchar का उपयोग कर सकते है। IPv4 की लंबाई स्थिर है, लेकिन IPv6 की स्थिति अत्यधिक परिवर्तनशील हो सकती है।

जब तक आपके पास इसे बाइनरी के रूप में संग्रहीत करने का एक अच्छा कारण नहीं है, तब तक एक स्ट्रिंग (पाठ) प्रकार के साथ रहें।


39
IPv6 की लंबाई बहुत तय है - 128 बिट्स।
Broam

4
जब तक आप डेटा के बारे में बात कर रहे हैं, मानव कभी नहीं पढ़ेगा या भारी मात्रा में डेटा नहीं होगा, यह सबसे अच्छा जवाब है।
एरेन कैम्ब्रिज

10
बाइनरी का उपयोग करने का एक सरल कारण और तार नहीं: द्विआधारी संस्करण आईपी ​​पते की संख्यात्मक सीमा की जांच की अनुमति देता है ! पाठ संस्करण नहीं है। यह निश्चित रूप से आवश्यक उपयोग पर निर्भर करता है, लेकिन द्विआधारी संख्या अधिक उपयोगी होती है क्योंकि उनका वास्तविक अर्थ होता है।
कोडिंग

4
varchar DB में काफी अधिक स्थान लेता है। 32-बिट IPv4 पता संख्यात्मक रूप से संग्रहीत करने के लिए 4 बाइट्स लेता है, और 128-बिट IPv6 पता संख्यात्मक रूप से संग्रहीत करने के लिए 16 बाइट्स लेता है। इस बीच, उस IPv4 पते को स्ट्रिंग के रूप में संग्रहीत करने के लिए 15 बाइट्स लगते हैं और IPv6 पते को स्ट्रिंग के रूप में 39 बाइट्स तक ले जा सकता है।
हारून शुल्त्स

1
varbinary (16) जाने का रास्ता है
jjxtra

17

यहाँ कुछ कोड को IPV4 या IPv6 को varchar फॉर्मेट में बाइनरी (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 के लिए त्रुटिपूर्ण रूप से काम किया। एक गोल यात्रा रूपांतरण ने केवल मामूली अंतर दिखाया जहां 0 को ipv6 (अग्रणी और निम्नलिखित) से छंटनी की गई थी।
crokusek

1
ToBinary () में, क्वेरी योजना और fn_varbintohexstr () के उपयोग के साथ कुछ समस्याओं को मारा, जो नियतात्मक के रूप में चिह्नित नहीं है। कैसे और किसके लिए '।' अनुभाग: @ vbzone = कन्वर्ट (varbinary (2), Convert (smallint, @ token)) का चयन करें? समतुल्य लगता है। @ ज़ोन या xml इंजन के लिए कोई ज़रूरत नहीं है? अच्छा स्पीडअप लगता है अगर xml इंजन ':' से भी किसी तरह हटा दिया जाए।
क्रोकुसेक

concat_ws ('।', (IPAddr & 0xFF000000) >> 24, (IPAddr & 0xFF0000) >> 16, (IPAddr & 0xFF00) >> 8, (IPAddr & 0xFF00) एक आईपी पते के बिना एक लंबे समय तक एक आईपी एड्रेस वाले एक लंबे अरसे में परिवर्तित हो जाएगा। मानव पठनीय रूप।
वाकिंग 2

@ aking2 - यह SQL सर्वर पर लागू नहीं होता है >> >> समर्थित नहीं है
एलेक्स

ध्यान दें कि एक बग है fn_ConvertIpAddressToBinary। देखें। Clock का जवाब और मेरा
एलेक्स

10

जैसा कि मैंने दोनों हैंडल करना चाहते हैं IPv4और IPv6, मैं उपयोग कर रहा हूँ VARBINARY(16)और निम्नलिखित SQL CLRकार्यों कन्वर्ट करने के लिए textबाइट्स आईपी पते प्रस्तुति और रिवर्स:

[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[]स्ट्रिंग में कनवर्ट करने के लिए एक ही वर्ग का उपयोग कर सकते हैं । यदि VARBINARYआप SQL में बदलना चाहते हैं :

--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 छोटे मार्ग को पसंद करूंगा। यह कहते हुए कि, मैं varchar (48) का उपयोग कर रहा हूँ क्योंकि मुझे इसका उपयोग करना है sys.dm_exec_connections...

अन्यथा। मार्क रेडमैन के उत्तर में पिछले SO बहस प्रश्न का उल्लेख है ।


4
वास्तविक हम होगा देख आईपीवी 6
Pacerier

10
वास्तविक रूप से हम वर्ष 2000 को कुछ समय के लिए नहीं देखेंगे, साथ ही कुछ बाइट्स को बचाने के लिए 2 अंकों की तारीखों का उपयोग कर सकते हैं। अरे रुको।
एरिक जे

1

धन्यवाद RBarry। मैं एक साथ एक आईपी ब्लॉक आवंटन प्रणाली रख रहा हूं और बाइनरी को संग्रहीत करना ही एकमात्र रास्ता है।

मैं IP ब्लॉक के CIDR प्रतिनिधित्व (उदा: 192.168.1.0/24) को एक वर्चर फ़ील्ड में संग्रहीत कर रहा हूं, और ब्लॉक की शुरुआत और अंत के द्विआधारी रूप को धारण करने के लिए 2 परिकलित फ़ील्ड का उपयोग कर रहा हूं। वहां से, मैं यह देखने के लिए तेज क्वेरी चला सकता हूं कि क्या एक दिया गया ब्लॉक पहले से ही आवंटित है या असाइन करने के लिए स्वतंत्र है।

मैंने समाप्त होने वाले आईपी पते की गणना करने के लिए आपके फ़ंक्शन को संशोधित किया है:

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 पते की श्रेणियों पर फ़िल्टर करना चाहते हैं, तो मैं इसे चार पूर्णांकों में तोड़ दूंगा।


1
एक सीमा क्या है? सभी सबनेट 8 बाइट नहीं हैं। इस होस्ट के नेटवर्क के लिए IP पतों की सीमा क्या है: 50.50.50.50/20?
ब्रैडली क्रेडर

2
इंटेगर 0-255 के मूल्य को स्टोर करने के लिए बहुत बड़े हैं। इसके बजाय एक टायलिन्ट का उपयोग करें।
सैंडरॉक

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

वास्तव में एक बग है
एलेक्स

0

निम्नलिखित उत्तर एम। टर्नहौट और जेरी बर्चलर द्वारा इस प्रश्न के उत्तर पर आधारित है, लेकिन निम्नलिखित सुधारों के साथ:

  • गैर-दस्तावेजी कार्य (के उपयोग बदला गया sys.fn_varbintohexsubstring, fn_varbintohexstrके साथ) CONVERT()के लिए द्विआधारी शैलियों
  • द्विआधारी शैलियों के लिए XML "हैक्स" ( CAST('' as xml).value('xs:hexBinary())) के साथ प्रतिस्थापितCONVERT()
  • जेरी बर्चलर के कार्यान्वयन में फिक्स्ड बग fn_ConvertIpAddressToBinary(जैसा कि C.Plock द्वारा बताया गया है )
  • मामूली वाक्यविन्यास चीनी जोड़ें

कोड SQL Server 2014 और SQL सर्वर 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) के अधिकांश (आमतौर पर इस्तेमाल किए जाने वाले) को पार्स करने में सक्षम है। समारोह को समाप्त करने के लिए थिंक बाइनरी मान को हमेशा 16 बाइट मानने के लिए बाध्य करें, जिससे फ़ंक्शन के अंत में 0s कॉन्टेनेशन होता है।

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)अब तक का उपयोग कर रहा हूं मेरे लिए सब कुछ काम कर रहा है। सम्मिलित करें, अद्यतन करें, चुनें। मैंने अभी एक ऐप शुरू किया है जिसमें आईपी एड्रेस हैं, हालाँकि मैंने अभी तक ज्यादा देव कार्य नहीं किया है।

यहाँ का चयन बयान है:

select * From dbo.Server 
where  [IP] = ('132.46.151.181')
Go
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.