1

SQL Server で、IPv4 アドレスのテーブルを結合する最も簡単な方法は何ですか...

IPAddress
------------
10.70.80.34
10.70.81.60
10.70.81.205

CIDR 表記の IP 範囲の表に...

IPRange          Description
---------------  -----------
10.70.80.0/24    Sydney
10.70.81.0/25    Melbourne
10.70.81.128/25  Perth

IP 範囲テーブルの行数は 100 未満になります。

4

4 に答える 4

4

少数の行で問題ない次の関数を作成しました。大きなテーブルの場合、IP はバイナリ形式で保存する必要があります。

CREATE FUNCTION IPAddressInRange
(
    @IPAddress NVARCHAR(MAX),
    @IPRange NVARCHAR(MAX)
)
RETURNS BIT AS
BEGIN
    DECLARE @SlashPos INT = CHARINDEX('/', @IPRange);
    DECLARE @Network NVARCHAR(MAX) = SUBSTRING(@IPRange, 1, @SlashPos - 1);
    DECLARE @PrefixBits INT = CAST(SUBSTRING(@IPRange, @SlashPos + 1, 2) AS INT);

    DECLARE @IPAddressInt BIGINT =
        PARSENAME(@IPAddress, 4) * POWER(CAST(2 AS BIGINT), 24) +
        PARSENAME(@IPAddress, 3) * POWER(CAST(2 AS BIGINT), 16) +
        PARSENAME(@IPAddress, 2) * POWER(CAST(2 AS BIGINT), 8) +
        PARSENAME(@IPAddress, 1);

    DECLARE @NetworkInt BIGINT =
        PARSENAME(@Network, 4) * POWER(CAST(2 AS BIGINT), 24) +
        PARSENAME(@Network, 3) * POWER(CAST(2 AS BIGINT), 16) +
        PARSENAME(@Network, 2) * POWER(CAST(2 AS BIGINT), 8) +
        PARSENAME(@Network, 1);

    DECLARE @Mask BIGINT = POWER(CAST(2 AS BIGINT), 32) -
        POWER(CAST(2 AS BIGINT), 32 - @PrefixBits);

    RETURN CASE WHEN @IPAddressInt & @Mask = @NetworkInt THEN 1 ELSE 0 END;
END

使用例:

SELECT *
FROM IPAddressTable a
JOIN IPRangeTable r
ON dbo.IPAddressInRange(a.IPAddress, r.IPRange) = 1
于 2013-07-31T13:42:23.913 に答える
4

このParseName()シナリオでは、関数が役立つ場合があります

DECLARE @ips table (
   ip_address varchar(15)
);

INSERT INTO @ips (ip_address)
  VALUES ('10.70.80.34')
       , ('10.70.81.60')
       , ('10.70.81.205');

SELECT ip_address
     , ParseName(ip_address, 4) As first_octet
     , ParseName(ip_address, 3) As second_octet
     , ParseName(ip_address, 2) As third_octet
     , ParseName(ip_address, 1) As fourth_octet
FROM   @ips

結果

ip_address      first_octet   second_octet   third_octet  fourth_octet
--------------- ------------- -------------- ------------ -------------
10.70.80.34     10            70             80           34
10.70.81.60     10            70             81           60
10.70.81.205    10            70             81           205
于 2013-07-29T13:34:54.453 に答える
0

PostgreSQL を使用している場合は、同じことを行う簡単な方法があります。

CREATE OR REPLACE FUNCTION IPInRange(VARCHAR(16), VARCHAR(20))
RETURNS BOOLEAN AS $$
    SELECT CAST($1 AS inet) << CAST($2 AS inet);
$$ LANGUAGE SQL;
于 2015-07-13T21:28:57.707 に答える