Sql server 如何在SQL Server中将IPv6地址从十进制数字字符串转换为两个大整数?

Sql server 如何在SQL Server中将IPv6地址从十进制数字字符串转换为两个大整数?,sql-server,csv,ipv6,bigint,Sql Server,Csv,Ipv6,Bigint,我有一个包含IPv6地址的CSV文件,我正试图将其批量导入到sql server表中。CSV文件中的地址示例可能是“5582829593011472482352587446858530464”。我希望将IP地址存储到数据库中的两个bigint中,因为SQL bigint只能处理64位,而IPv6地址需要128位。我处理IPV4地址的导入代码是: SET @sql = ' INSERT INTO dbo.IPCountry SELECT REPLACE(ipFROM

我有一个包含IPv6地址的CSV文件,我正试图将其批量导入到sql server表中。CSV文件中的地址示例可能是“5582829593011472482352587446858530464”。我希望将IP地址存储到数据库中的两个bigint中,因为SQL bigint只能处理64位,而IPv6地址需要128位。我处理IPV4地址的导入代码是:

SET @sql = '
    INSERT INTO dbo.IPCountry
    SELECT
        REPLACE(ipFROM, ''"'', '''') AS ipFROM,
        REPLACE(ipTO, ''"'', '''') AS ipTO,
        CAST(REPLACE(countrySHORT, ''"'', '''') AS CHAR(2)) AS countrySHORT
    FROM OPENROWSET(
        BULK ''' + @Directory + 'IPCountry.csv'',
        FORMATFILE = ''' + @Directory + 'IPCountry.Xml''
    ) AS t1
';
exec sp_executesql @sql;

如何将128位IPv6值转换为两个bigint值?

基于您的示例正好是一个38个字符的数字字符串,我将其拆分为两半,并将每一半转换为bigint组件

下面是一个演示该过程并将其逆转的示例:

-- Prepare test variables
DECLARE @Source AS NVARCHAR(38)
DECLARE @ipFROMa AS BIGINT
DECLARE @ipFROMb AS BIGINT
DECLARE @Destination AS NVARCHAR(38)

SET @Source = '55828295930114724823525874468560830464'

-- Split Source into TWO strings and then each into a BIGINT
SET @ipFROMa = (SELECT CAST(SUBSTRING(@Source,1,19) AS BIGINT))
SET @ipFROMb = (SELECT CAST(SUBSTRING(@Source,20,19) AS BIGINT))

-- Test returning BIGINTs into one IPv6 string
SET @Destination = (SELECT 
                        CAST( 
                            CAST(@ipFROMa AS NVARCHAR(19)) +
                            CAST(@ipFROMb AS NVARCHAR(19))
                             AS nvarchar(38)))

-- Display the values for verification
SELECT @Source, @ipFROMa, @ipFROMb, @Destination
结果:

5582829593011472482352587468560830464 5582829593011472482 352587468560830464 5582829593011472482352587468560830464


基于您的示例正好是一个38个字符的数字字符串,我将它一分为二,并将每一半转换为BIGINT组件

下面是一个演示该过程并将其逆转的示例:

-- Prepare test variables
DECLARE @Source AS NVARCHAR(38)
DECLARE @ipFROMa AS BIGINT
DECLARE @ipFROMb AS BIGINT
DECLARE @Destination AS NVARCHAR(38)

SET @Source = '55828295930114724823525874468560830464'

-- Split Source into TWO strings and then each into a BIGINT
SET @ipFROMa = (SELECT CAST(SUBSTRING(@Source,1,19) AS BIGINT))
SET @ipFROMb = (SELECT CAST(SUBSTRING(@Source,20,19) AS BIGINT))

-- Test returning BIGINTs into one IPv6 string
SET @Destination = (SELECT 
                        CAST( 
                            CAST(@ipFROMa AS NVARCHAR(19)) +
                            CAST(@ipFROMb AS NVARCHAR(19))
                             AS nvarchar(38)))

-- Display the values for verification
SELECT @Source, @ipFROMa, @ipFROMb, @Destination
结果:

5582829593011472482352587468560830464 5582829593011472482 352587468560830464 5582829593011472482352587468560830464


我猜countrySHORT与您将IPv6转换为bigint无关?ipFROM和ipTO是否都应该是2个bigint字段,即:ipFROMa和ipFROMb等?正确,countrySHORT只是CSV文件中导入到表中的另一个值。是的,IPv6版本将需要将128位IPv6值拆分为一个较高的bigint值和一个较低的bigint值。我猜countrySHORT与您将IPv6转换为bigint无关?ipFROM和ipTO是否都应该是2个bigint字段,即:ipFROMa和ipFROMb等?正确,countrySHORT只是CSV文件中导入到表中的另一个值。是的,IPv6版本将需要将128位IPv6值拆分为一个上bigint值和一个下bigint值。Don,如果我只需要将128位值存储在两个bigint中,而不需要对它们执行任何数学运算,这将非常有效,例如,查找介于ipFROM和ipTO之间的值(countrySHORT)。IPv6需要分为上64位值和下64位值。因此,使用您的示例,ipFROMa将包含IPv6的低64位值,ipFROMb将包含IPv6的高64位值。IPv6地址通常由八组四个十六进制数字组成,用冒号分隔。它们分为两部分:64位(子)网络前缀和64位接口标识符。但是,您似乎正在将它们作为完整的十进制数检索。如果原始十六进制到十进制的转换将最重要的数字保留在左边,然后像我上面所做的那样将其一分为二,那么结果应该是:ipFROMa应该是“(子)网络前缀”,ipFROMb应该是“接口标识符”,但是,它们不是普通的十六进制格式。Don,如果我只需要将128位的值存储在两个bigint中,而不需要对它们执行任何数学运算,例如查找介于ipFROM和ipTO之间的值(countrySHORT),那么这将非常有效。IPv6需要分为上64位值和下64位值。因此,使用您的示例,ipFROMa将包含IPv6的低64位值,ipFROMb将包含IPv6的高64位值。IPv6地址通常由八组四个十六进制数字组成,用冒号分隔。它们分为两部分:64位(子)网络前缀和64位接口标识符。但是,您似乎正在将它们作为完整的十进制数检索。如果原始十六进制到十进制的转换将最重要的数字保留在左边,然后像我上面所做的那样将其一分为二,那么结果应该是:ipFROMa应该是“(子)网络前缀”,ipFROMb应该是“接口标识符”,但是,它们不是普通的十六进制格式。