執行這個東西做的伎倆:因爲需要一個完整的掃描
DECLARE @ipaddress nvarchar(16) = N'87.217.221.22'
SELECT *
FROM CityIp
WHERE
(
CAST(PARSENAME(IpStart, 4) AS bigint) * 256 * 256 * 256 +
CAST(PARSENAME(IpStart, 3) AS bigint) * 256 * 256 +
CAST(PARSENAME(IpStart, 2) AS bigint) * 256 +
CAST(PARSENAME(IpStart, 1) AS bigint)
)
<=
(
CAST(PARSENAME(@ipaddress, 4) AS bigint) * 256 * 256 * 256 +
CAST(PARSENAME(@ipaddress, 3) AS bigint) * 256 * 256 +
CAST(PARSENAME(@ipaddress, 2) AS bigint) * 256 +
CAST(PARSENAME(@ipaddress, 1) AS bigint)
)
AND
(
CAST(PARSENAME(IpEnd, 4) AS bigint) * 256 * 256 * 256 +
CAST(PARSENAME(IpEnd, 3) AS bigint) * 256 * 256 +
CAST(PARSENAME(IpEnd, 2) AS bigint) * 256 +
CAST(PARSENAME(IpEnd, 1) AS bigint)
)
>=
(
CAST(PARSENAME(@ipaddress, 4) AS bigint) * 256 * 256 * 256 +
CAST(PARSENAME(@ipaddress, 3) AS bigint) * 256 * 256 +
CAST(PARSENAME(@ipaddress, 2) AS bigint) * 256 +
CAST(PARSENAME(@ipaddress, 1) AS bigint)
)
不幸的是,查詢速度很慢。
編輯 上述查詢將與ipv4地址一起使用。爲了應對IPv6地址我會用一個CLR標量函數如下所示:
public partial class UserDefinedFunctions
{
[SqlFunction(DataAccess=DataAccessKind.None, IsDeterministic=true, IsPrecise=true, SystemDataAccess=SystemDataAccessKind.None)]
[return: SqlFacet(MaxSize=16)]
public static SqlBinary TryParseIPAddress([SqlFacet(MaxSize=40)] SqlString iPAddress)
{
if (iPAddress.IsNull) return SqlBinary.Null;
IPAddress address;
if (IPAddress.TryParse(iPAddress.Value, out address))
{
return new SqlBinary(address.GetAddressBytes());
}
else return SqlBinary.Null;
}
}
然後使用它是這樣的:
DECLARE @ipaddress varbinary(16) = dbo.TryParseIPAddress(N'2001:0db8:85a3:0000:0000:8a2e:0370:7334')
SELECT *
FROM CityIp
WHERE
dbo.TryParseIPAddress(IpStart) <= @ipaddress
AND dbo.TryParseIPAddress(IpEnd) >= @ipaddress
編輯: 一兩件事,將加快東西是加入兩個二進制以二進制格式存儲IpStart和IpEnd的計算列。但是,最大的性能改進是如圖所示應用Relational Interval Tree在下面的文章:
Interval Queries in SQL Server
你是如何存儲的IP地址?您應該將它們存儲爲「int」(用於IPv4)或「varbinary(16)」用於IPv4 + IPv6,而不是字符串。 – Dai
另外,您應確保這些IP地址範圍內部連續。 – Dai
如果您將它們存儲爲字符串(!),這可能會幫助您https://msdn.microsoft.com/en-us/library/ms187928.aspx –