在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行。
答案 0 :(得分: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
答案 1 :(得分:4)
我写了以下函数,对于少量行是可以的。对于较大的表,IP应存储in binary form。
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
答案 2 :(得分:1)
就像你用其他任何语言一样 - 用一堆拼写的逻辑:
and
)面具后,从左到右一次比较一个数字SQL Server唯一特别之处在于您要避免使用函数(内联表值函数除外)。您还需要考虑到SQL操作系统在字符串操作方面的速度很慢。
如果值存储为字符串,我建议写一个CLR函数。在.NET代码中,这实现起来相当简单,并且CLR标量值函数的调用开销并不大。但是,您将无法在任何一个表上使用索引。
如果IPRange是一个普通的查找表,你可能会没事的。但是,如果要编写返回属于特定范围的所有IP地址的查询,则可能会出现问题。在这种情况下,我建议在单独的字段中存储IP地址的四个整数以及掩码的整数。这样就可以进行索引,并且连接逻辑变成一个相当简单的表达式。
答案 3 :(得分: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;