日期:2014-05-18  浏览次数:20459 次

请教一个数据库设计方案
表User
ID Area Name IP Mask Gateway Note 
表IP
ID IP Mask Gateway Used

当我在User表中选用一个IP后,用触发器同步更新IP表中对应IP的Used值为1,表示已占用,当修改或删除User表中的IP后,将Used改为0表示空闲,这是没有问题的,但实际情况比这复杂,User表中的IP有可能是一段,或者不连继的几个,比如192.168.0.2-10,或者 192.168.0.2,192.168.0.5,这种情况我也可以在触发器中分析处理,把这些IP都改成占用状态,但是我在User表按IP字段搜索就出问题了,比如IP是192.168.0.2-10,我搜索User表中的IP,条件是WHERE IP='192.168.0.3',这就搜不到了,求指导,我目前的相法是把User表分成两张,把IP部分独立出来,或者在IP表中增加一个UserID,搜索IP的时候在IP表中搜索。不过我的IP表有约50万记录,User表有30多个字段,目前已经关联查询3张表了(不过这些表都只有几十条记录),如果把IP表也关联过来,那性能可能会比较差,我现在用的是分页显示,SELECT语句已经很复杂了。

------解决方案--------------------
你是IP的搜索范围有疑问?

一般有两种方法进行比较,一种是转换成整数,然后比较,参考如下:
/*
标题:字符串IP地址和IP数值互换函数
作者:爱新觉罗·毓华(十八年风雨,守得冰山雪莲花开) 
时间:2009-07-17
地点:新疆乌鲁木齐
*/

SQL code

--1. 字符串IP地址转换成IP数值函数。
CREATE FUNCTION dbo.f_IPtoInt(@ip char(15))RETURNS bigint
AS
BEGIN
    DECLARE @re bigint
    SET @re = 0
    SELECT @re = @re + LEFT(@ip , CHARINDEX('.' , @ip + '.') - 1) * ID ,
           @ip = STUFF(@ip , 1 , CHARINDEX('.' , @ip + '.') , '')
    FROM
    (
        SELECT ID = CAST(16777216 as bigint)
        UNION ALL SELECT 65536
        UNION ALL SELECT 256
        UNION ALL SELECT 1
    ) a
    RETURN(@re)
END
GO

select dbo.f_IPtoInt('192.168.20.179') ip_int

/*
ip_int               
-------------------- 
3232240819

(所影响的行数为 1 行)
*/

drop function dbo.f_IPtoInt


--2. 字符串IP地址转换成IP数值函数。
CREATE FUNCTION dbo.f_InttoIP(@IP bigint)RETURNS varchar(15)
AS
BEGIN
    DECLARE @re varchar(15)
    SET @re = ''
    SELECT @re = @re + '.' + CAST(@IP/ID as varchar) , @IP = @IP % ID
    FROM
    (
        SELECT ID = CAST(16777216 as bigint)
        UNION ALL SELECT 65536
        UNION ALL SELECT 256
        UNION ALL SELECT 1
    ) a
    RETURN(STUFF(@re , 1 , 1 , ''))
END
GO

SELECT dbo.f_InttoIP(3232240819) ip_varchar

/*
ip_varchar      
--------------- 
192.168.20.179

(所影响的行数为 1 行)
*/

DROP FUNCTION dbo.f_InttoIP

------解决方案--------------------
探讨
我想过转成数值,但是数值不能模糊查询,我的IP字段是要支持模糊查询的,而且转成数值也不能解决我的问题。
我的问题主要是,如果在User表中表示一段IP,或者不连续的n个IP,而且要能将中间的IP搜索出来。如果我IP字段的值是192.168.0.2-10,搜索192.168.0.3是搜索不出来的。

------解决方案--------------------
如果是 192.168.0.2-10 这样,
那你得建两个字段来存储:
开始段:192.168.0.2
截止段:192.168.0.10

对于多个逗号分隔的,得建一个子表来存。