1

私はSQL2005を使用しています。ゼロの複数の連続したセクションを処理できるように、誰かがこのステートメントを変更するのを手伝ってくれることを望んでいます。このステートメントは、IPv6アドレスをバイナリに変換します。

次のIPv6アドレスがあるとします:2001:db8:85a3:0000:0000:8a2e:370:7334。

2001:db8:85a3 :: 8a2e:370:7334と書き直して、ゼロの連続するセクションを取り除くことができます。

ただし、以下のSQLステートメントは、完全な表記で2001:db8:85a3:0000:0000:8a2e:370:7334と記述されている場合にのみ、上記のIPv6アドレスを処理できるため、バイナリ結果は0x20010DB885A3000000008A2E03707334になります。

2001:db8:85a3 :: 8a2e:370:7334として記述されたIPv6アドレスを処理できるように、以下のステートメントをどのように変更できますか?または::1のようなアドレスでさえ?

DECLARE    @ipstr VARCHAR(50)
SET        @ipstr = '2001:db8:85a3::0000:8a2e:370:7334'
SELECT     CAST('' AS XML).value('xs:hexBinary( sql:column("y.ips") )', 'varbinary(16)')
FROM       (
            SELECT ips = (
                          SELECT  RIGHT('0000' + SUBSTRING(ips, NUMBER, CHARINDEX(':', ips, NUMBER) - NUMBER), 4)
                          FROM    master.dbo.spt_values
                                 ,(SELECT ips = ':' + @ipstr + ':') x
                          WHERE   TYPE = 'P'
                                  AND NUMBER BETWEEN 2 AND LEN(ips)
                                  AND SUBSTRING(ips, NUMBER-1, 1) = ':'
                          FOR     XML PATH('')
                         )
           ) y
4

2 に答える 2

1

これはおそらく最もクリーンなソリューションではありませんが、機能します。

WITH cteRawSections (RowNumber, ips) As
(
   -- Split the address into sections:
   SELECT
      ROW_NUMBER() OVER (ORDER BY number),
      Substring(ips, number, CharIndex(':', ips, number) - number)
   FROM
      master.dbo.spt_values
      CROSS APPLY
      (SELECT ips = ':' + @ipstr + ':') As c
   WHERE
      type = 'P'
   And
      number Between 2 And Len(ips)
   And
      Substring(ips, number - 1, 1) = ':'
),
cteSections (RowNumber, ips) As
(
   -- Pad the non-empty sections:
   SELECT
      RowNumber,
      Right('0000' + ips, 4)
   FROM
      cteRawSections
   WHERE
      ips != ''

   UNION ALL

   -- Include the missing sections:
   SELECT
      (SELECT Min(RowNumber) FROM cteRawSections WHERE ips = ''),
      '0000'
   FROM
      master.dbo.spt_values
   WHERE
      type = 'P'
   And
      number >= 1
   And
      number <= (SELECT 8 - Count(1) FROM cteRawSections WHERE ips != '')
),
cteJoined As
(
   -- Join the sections in order:
   SELECT ips = 
   (
      SELECT ips
      FROM cteSections
      ORDER BY RowNumber
      FOR XML PATH(''), TYPE
   ).value('.', 'varchar(max)')
)
SELECT
   CAST('' As XML).value('xs:hexBinary(sql:column("y.ips"))', 'varbinary(16)')
FROM
   cteJoined As y
;

http://www.sqlfiddle.com/#!3/d41d8/7258/0

注意:サンプルアドレス2001:db8:85a3:0000:0000:0000:8a2e:370:7334は長すぎて、有効なIPv6アドレスにはなりません。

于 2012-12-17T19:21:34.317 に答える
0

Set@ipstrステートメントの後にこれを挿入します。

    declare @colonCount int = len(@ipstr)-len(replace(@ipstr,':',''))
    if(@colonCount<7)
        set @ipstr=replace(@ipstr,'::', replicate( ':0',7-@colonCount+1) +':')
于 2014-03-05T04:38:06.697 に答える