2

IP 地址以下列任何一种方式存储在我的表中。

192.12.34.12
192.12.#.12
192.#.34.12

现在在我的应用程序中,我想通过使用 .net 代码捕获登录用户的 IP 地址来自动验证用户 IP 地址。

现在如果用户 IP 是

192.12.34.12
192.12.45.12

192.56.34.12-- it should be valid.
191.12.34.12-- Invalid

如何创建一个 SQL 查询或一个存储过程来验证登录用户的 IP 地址与此表的关系?

4

3 回答 3

4

尝试使用LIKE运算符,如下所示:

SELECT *
FROM IPRecords
WHERE @UsersIp like replace(IP, '#', '%')

但是,如果表中有很多记录(它不能使用任何索引),这种方法在性能方面可能会有很大问题。

如果性能确实是一个问题,另一种方法可能是:

  • 将 IP 拆分为四个数字列
  • 用于null表示通配符(例如,您的最后一条规则将变为192, null, 34, 12
  • 在客户端,将 IP 拆分为相应的 4 部分,并使用如下条件:

    WHERE (IP1=@IP1 OR IP1 is null) AND (IP2=@IP2 OR IP2 is null) AND ...

这样,我认为您可以在需要时使用四列上的索引来加快速度。

于 2012-05-04T15:04:37.023 回答
3

您可以使用 PARSENAME 函数将 IP 地址值拆分为四个部分并分别进行比较。

创建和填充测试数据脚本

CREATE TABLE ipaddresses
( 
    ip VARCHAR(20) NOT NULL
);

INSERT INTO ipaddresses (ip) VALUES
    ('192.12.34.12'),
    ('192.12.#.12'),
    ('192.#.34.12');

情景#1

DECLARE @userip VARCHAR(20)
SET     @userip = '192.56.34.12'

;WITH ips AS
(
    SELECT  REPLACE(ip, '#', '%') AS ip
    FROM    ipaddresses
)
SELECT  COUNT(ip) AS validcount
FROM    ips
WHERE   PARSENAME(@userip, 1) LIKE PARSENAME(ip, 1)
AND     PARSENAME(@userip, 2) LIKE PARSENAME(ip, 2)
AND     PARSENAME(@userip, 3) LIKE PARSENAME(ip, 3)
AND     PARSENAME(@userip, 4) LIKE PARSENAME(ip, 4);

VALIDCOUNT
----------
    1

情景#2

DECLARE @userip VARCHAR(20)
SET     @userip = '191.12.34.12'

;WITH ips AS
(
    SELECT  REPLACE(ip, '#', '%') AS ip
    FROM    ipaddresses
)
SELECT  COUNT(ip) AS validcount
FROM    ips
WHERE   PARSENAME(@userip, 1) LIKE PARSENAME(ip, 1)
AND     PARSENAME(@userip, 2) LIKE PARSENAME(ip, 2)
AND     PARSENAME(@userip, 3) LIKE PARSENAME(ip, 3)
AND     PARSENAME(@userip, 4) LIKE PARSENAME(ip, 4);

VALIDCOUNT
----------
   0
于 2012-05-04T15:15:18.133 回答
1

您可以做一个声明,在每个位置(点之间)用“#”替换访问者 IP 的数字,并执行常规的 WHERE 子句。因此,您会得到一个带有 where 子句的语句,其中包含五个比较(一个用于直接匹配,四个用于每个位置的替换 #)。

您可以使用 CHARINDEX 来查找点,并使用 SUBSTRING 来构建比较 varchars。

于 2012-05-04T15:01:19.573 回答