2017-02-06 9 views
2

-----------------------元の質問---------------------- -SQLの範囲(1.0.0.0〜1.0.0.24)として1.0.0.0/24をどのように読むことができますか?

私はIP 1.0.88.12を持っていると仮定します。私はIPv4データベースに対して照会し、正しい国を返すことを望みます。

データベース(geodata)テーブル(IP)は、次の形式でIPアドレスを一覧表示されている:ここ

network  country 
--------------------- 
1.0.0.0/24  1212 
1.0.1.0/24  1212 
...   ... 
1.0.88.0/22 3000 

、私は1.0.88.0/221.0.88.221.0.88.01.0.88.11.0.88.2を表すと仮定する。

networkが実際には範囲であることを理解できるように、このテーブルをクエリするにはどうすればよいですか?

-----------------------進行中の更新-------------------- ---

私の推測では間違っていたので、すべての入力のおかげで!しかしまだ1つの質問は傑出した。

(私が今持っているものの)次の例ください:ポイントがある

/** 
* Convert IP 4-octed set into integer 
*/ 
create function [dbo].[IPAddressToInteger] (@IP as varchar(15)) 
returns bigint 
as 
begin 
return (convert(bigint, parsename(@IP,1)) + 
     convert(bigint, parsename(@IP,2)) * 256 + 
     convert(bigint, parsename(@IP,3)) * 256 * 256 + 
     convert(bigint, parsename(@IP,4)) * 256 * 256 * 256) 
end 


/** 
* Calculate CIDR from mask 
*/ 
create function [dbo].[CIDRFromMask] (@mask as bigint) 
returns varchar(5) 
as 
begin 
    declare @maskCalc bigint 
    select @maskCalc = dbo.IPAddressToInteger('255.255.255.255') - @mask + 1 

    declare @logCalc int 
    select @logCalc = (32 - log(@maskCalc, 2)) 

    return '/' + cast(@logCalc as varchar(5)) 
end 

select dbo.IPAddressToInteger('195.65.254.11'); -- 3275881995 
select select dbo.CIDRFromMask('3275881995'); -- /2 

select '195.65.254.11/2' from geodata.IP  -- 0 results 
select '195.65.254.0/2' from geodata.IP  -- 1 result (seems correct) 

を:私はIP + CIDRを連結する場合、私は私の知る限りである(GEOデータベースに対応したIPを見つけることができません。完全なデータベース)。私が手動で195.65.254.11/2195.65.254.0/2に変換すると結果は見つかりますが、これはやり方ではないと思います。したがって:どのステップはまだ私は行方不明ですか?

+3

注有効なアドレス '1.0.88.0/22'は通常、範囲は' 1.0ではないことを、「最初の22ビットがネットワークである」を意味すること。 88.1'-1.08.8.22'。これはあなた自身のIP範囲形式ですか、あるいはちょうどCIDR表記を誤解していますか?それが地理データ表であるとすれば、ネットワークはCIDRであると思うので、 '1.0.0.0/24'は' 1.0.0.1'-'1.0.0.255'にマップされます。 – Luaan

+1

あなたはこれが本当に必要なのですか? [Subnetting here](https://en.wikipedia.org/wiki/Subnetwork)=> 'セクション 'サブネットとホスト数' –

+1

または[CIDR表記法についてはこちらを読む](https://en.wikipedia .org/wiki/Classless_Inter-Domain_Routing#CIDR_notation) –

答えて

2

IP範囲をInt32に変換しようとする場合があります。この方法では、これらの間隔を照会する方が簡単です。あなたは一般的な考え方については、以下のリンクを参照することができ :
@Dogucan

まず第一で考えに拡大 https://www.periscopedata.com/blog/comparing-ip-addresses-in-sql.html

+0

まだ斜体を範囲に変換する必要があります。その参考文献では、SQL Serverについてはこれをカバーしていません。 –

0

私は「/ 24」を無視して(整数にIP文字列を変換します)。 "/"部分を使用して、ネットワークルートに使用されているビット数(この場合は24)を調べます。これを使用して、IPアドレスに使用されているビット数を調べます。この場合、それは32-24 = 8です.8ビットは2^8 = 256の範囲に相当します(IPはゼロに基づいているため、私は0..255のIP範囲を与えるために1を取ります)。

これを元のIPアドレスに追加して、終了IPを取得し、文字列に変換し直します。

これは結果を与える
declare @ip varchar(50) = '1.0.0.0/24' 


;WITH CTE 
AS 
(
    SELECT 
     convert(bigint, SUBSTRING(parsename(@ip, 1),0, CHARINDEX('/',parsename(@ip, 1)))) + 
     convert(bigint, parsename(@ip, 2)) * 256 + 
     convert(bigint, parsename(@ip, 3)) * 65536 + 
     convert(bigint, parsename(@ip, 4)) * 16777216 as StartIPInt, 
     convert(bigint, SUBSTRING(parsename(@ip, 1),0, CHARINDEX('/',parsename(@ip, 1)))) + 
     convert(bigint, parsename(@ip, 2)) * 256 + 
     convert(bigint, parsename(@ip, 3)) * 65536 + 
     convert(bigint, parsename(@ip, 4)) * 16777216 + 
     POWER(2,32- convert(bigint, SUBSTRING(parsename(@ip, 1),CHARINDEX('/',parsename(@ip, 1))+1,20)))-1 AS EndIpInt 
) 
, 
IPRange 
As 
(
    SELECT 
     StartIPInt/16777216 As StartOctet1, 
     (StartIPInt - (StartIPInt/16777216) * 16777216) /65536 As StartOctet2, 
     (StartIPInt - ((StartIPInt/65536) * 65536))/256 As StartOctet3, 
     (StartIPInt - ((StartIPInt/256) * 256)) As StartOctet4, 
     EndIpInt/16777216 As EndOctet1, 
     (EndIpInt - (EndIpInt/16777216) * 16777216) /65536 As EndOctet2, 
     (EndIpInt - ((EndIpInt/65536) * 65536))/256 As EndOctet3, 
     (EndIpInt - ((EndIpInt/256) * 256)) As EndOctet4 
    FROM CTE 
) 
SELECT CAST(StartOctet1 AS VARCHAR(3)) + '.' + CAST(StartOctet2 AS VARCHAR(3)) + '.' + CAST(StartOctet3 AS VARCHAR(3)) + '.' + CAST(StartOctet4 AS VARCHAR(3)) StartIPAddress, 
     CAST(EndOctet1 AS VARCHAR(3)) + '.' + CAST(EndOctet2 AS VARCHAR(3)) + '.' + CAST(EndOctet3 AS VARCHAR(3)) + '.' + CAST(EndOctet4 AS VARCHAR(3)) EndIPAddress 
FROM IPRange 

:コードのクリーンビットのために

StartIPAddress EndIPAddress 
1.0.0.0   1.0.0.255 

はとIPRange CTEを置き換える:

IPRange 
As 
(
-- 1.0.0.0 0x0000000001000000 
-- 0.1.0.0 0x0000000000010000 
-- 0.0.1.0 0x0000000000000100 
-- 0.0.0.255 0x00000000000000FF 
    SELECT 
     CAST(SUBSTRING(CAST(StartIPInt AS varbinary),0, 6) AS tinyInt) AS StartOctet1, 
     CAST(SUBSTRING(CAST(StartIPInt AS varbinary),5, 2) AS tinyInt) AS StartOctet2, 
     CAST(SUBSTRING(CAST(StartIPInt AS varbinary),6, 2) AS tinyInt) AS StartOctet3, 
     CAST(SUBSTRING(CAST(StartIPInt AS varbinary),7, 2) AS tinyInt) AS StartOctet4, 
     CAST(SUBSTRING(CAST(EndIPInt AS varbinary),0, 6) AS tinyInt) AS EndOctet1, 
     CAST(SUBSTRING(CAST(EndIPInt AS varbinary),5, 2) AS tinyInt) AS EndOctet2, 
     CAST(SUBSTRING(CAST(EndIPInt AS varbinary),6, 2) AS tinyInt) AS EndOctet3, 
     CAST(SUBSTRING(CAST(EndIPInt AS varbinary),7, 2) AS tinyInt) AS EndOctet4 
    FROM CTE 
) 
1

それは実際にCIDR表記だ場合は、することができます提案された@DoğukanTunçとしてintに変換し、マスクを適用し、CIDRのアドレス部分と比較する。IPとCIDRがビット値(0または1)を返すという2つの引数をとって機能を作るのは良い考えでしょう。 ここでは機能を説明するコードだけを示しています。エラーが処理されない、IPアドレスとCIDRを想定

declare @IP nvarchar(20)='192.168.1.111'; 
declare @CIDRADDR nvarchar(20)='192.168.0.0/22'; 


--convert to int 
declare @IP_as_int bigint; 
select @IP_as_int=convert(bigint, parsename(@ip, 1)) + 
    convert(bigint, parsename(@ip, 2)) * 256 + 
    convert(bigint, parsename(@ip, 3)) * 65536 + 
    convert(bigint, parsename(@ip, 4)) * 16777216; 

--calculate mask from CIDR: can specify table, or use CASE or use cycle 
--mst performance will have CASE, but am to lazy to write CASE with 32 cases 
--the result should be N filled bits from left side of 32-bit integer, where N is number after/in CIDR notation 
declare @mask bigint=0; 
declare @m1 bigint 
declare @m2 bigint=0x80000000; 
select @m1=CHARINDEX('/',@CIDRADDR); 
select @m1=cast(SUBSTRING(@CIDRADDR,@m1+1,2) as int); 

while(@m1>0) 
begin 
    set @mask = @mask | @m2; 
    set @[email protected] /2; 
    set @[email protected]; 
end 



--calculate back 
declare @IP_as_bin binary(4)=cast(@IP_as_int & @mask as binary(4)); 
declare @maskedIP nvarchar(20)= cast(cast((substring(@IP_as_bin,1,1)) as int) as nvarchar)+'.' + 
    cast(cast((substring(@IP_as_bin,2,1)) as int) as nvarchar)+'.' + 
    cast(cast((substring(@IP_as_bin,3,1)) as int) as nvarchar)+'.' + 
    cast(cast((substring(@IP_as_bin,4,1)) as int) as nvarchar); 

--compare with CIDR address part 
select @m1=CHARINDEX('/',@CIDRADDR); 
if(SUBSTRING(@CIDRADDR,1,@m1-1)[email protected]) 
    print @IP + ' belongs to ' [email protected]; 
else 
    print @IP + ' doesn`t belong to ' [email protected]; 
関連する問題