MS Access SQL查询IP地址范围

时间:2014-05-16 06:26:17

标签: sql ms-access

IP地址作为文本值存储在Access数据库中,格式为192.168.0.1 - 192.168.0.254在联结表中。

连接表,例如区域

Name       IPAddress
Area1      192.168.0.1 - 192.168.0.254
Area2      192.168.1.1 - 192.168.1.254

我需要能够搜索这些范围之间的记录,例如

SELECT * FROM devices WHERE ipaddress = 192.168.0.1 /Returns record Name1

SELECT * FROM tablename WHERE ipaddress BETWEEN 192.168.0.1 AND 192.168.0.25 /Returns record Name1,Name2,Name3,etc

2 个答案:

答案 0 :(得分:1)

要搜索一系列IP地址,您可以使用像这样的小VBA功能

Option Compare Database
Option Explicit

Public Function ZeroPaddedIP(IP As String) As String
    Dim rtn As String, octets() As String, octet As Variant
    rtn = ""
    octets = Split(IP, ".")
    For Each octet In octets
        rtn = rtn & "." & Format(Val(octet), "000")
    Next
    ZeroPaddedIP = Mid(rtn, 2)  ' trim leading "."
End Function

它用前导零填充八位字节,所以

ZeroPaddedIP("192.168.0.1") --> "192.168.000.001"

您的查询可以执行类似

的操作
SELECT * FROM tablename 
WHERE ZeroPaddedIP(ipaddress) BETWEEN "192.168.000.001" AND "192.168.000.025"

该查询将执行表扫描,因为它无法使用[ipaddress]上的任何现有索引。如果性能有问题,您可以考虑以填充形式存储您的IP地址(代替正常的非填充格式,或者除了正常的非填充格式之外)。

修改

对于名为[NetworkData]的测试表...

ID  IP             Description
--  -------------  -----------
 1  192.168.0.1    router     
 2  192.168.0.2    test server
 3  192.168.0.3    dev server 
 4  192.168.0.102  test client
 5  192.168.0.103  dev client 

...上面显示的VBA函数可以在这样的Access查询中使用...

SELECT
    IP,
    ZeroPaddedIP(IP) AS PaddedIP
FROM NetworkData

......产生以下结果......

IP             PaddedIP
-------------  ---------------
192.168.0.1    192.168.000.001
192.168.0.2    192.168.000.002
192.168.0.3    192.168.000.003
192.168.0.102  192.168.000.102
192.168.0.103  192.168.000.103

...但仅限于从Access本身执行查询。可以从以下查询获得相同的结果,但是如果从其他应用程序(如Excel)对Access数据库运行查询,则此结果将起作用:

SELECT
    IP,
    Right('000' & Octet1, 3) & '.' & Right('000' & Octet2, 3) & '.' & Right('000' & Octet3, 3) & '.' & Right('000' & Octet4, 3) AS PaddedIP
FROM
    (
        SELECT
            IP,
            Octet1,
            Octet2,
            Left(TheRest2, InStr(TheRest2, '.') - 1) AS Octet3, 
            Mid(TheRest2, InStr(TheRest2, '.') + 1) AS Octet4
        FROM
            (
                SELECT
                    IP,
                    Octet1,
                    Left(TheRest1, InStr(TheRest1, '.') - 1) AS Octet2, 
                    Mid(TheRest1, InStr(TheRest1, '.') + 1) AS theRest2
                FROM
                    (
                        SELECT 
                            IP, 
                            Left(IP, InStr(IP, '.') - 1) AS Octet1, 
                            Mid(IP, InStr(IP, '.') + 1) AS theRest1 
                        FROM NetworkData
                    ) AS q1
            ) AS q2
    ) AS q3

因此,如果您从Excel(或任何地方)查询数据并尝试使用

SELECT * FROM NetworkData 
WHERE IP Between '192.168.0.1' And '192.168.0.25'

你会得到以下不正确的结果

ID  IP             Description
--  -------------  -----------
 1  192.168.0.1    router     
 2  192.168.0.2    test server
 4  192.168.0.102  test client
 5  192.168.0.103  dev client 

而如果您使用

SELECT NetworkData.* 
FROM
    NetworkData
    INNER JOIN
    (
        SELECT
            IP,
            Right('000' & Octet1, 3) & '.' & Right('000' & Octet2, 3) & '.' & Right('000' & Octet3, 3) & '.' & Right('000' & Octet4, 3) AS PaddedIP
        FROM
            (
                SELECT
                    IP,
                    Octet1,
                    Octet2,
                    Left(TheRest2, InStr(TheRest2, '.') - 1) AS Octet3, 
                    Mid(TheRest2, InStr(TheRest2, '.') + 1) AS Octet4
                FROM
                    (
                        SELECT
                            IP,
                            Octet1,
                            Left(TheRest1, InStr(TheRest1, '.') - 1) AS Octet2, 
                            Mid(TheRest1, InStr(TheRest1, '.') + 1) AS theRest2
                        FROM
                            (
                                SELECT 
                                    IP, 
                                    Left(IP, InStr(IP, '.') - 1) AS Octet1, 
                                    Mid(IP, InStr(IP, '.') + 1) AS theRest1 
                                FROM NetworkData
                            ) AS q1
                    ) AS q2
            ) AS q3
    ) AS q4
        ON q4.IP = NetworkData.IP
WHERE q4.PaddedIP Between '192.168.000.001' And '192.168.000.025'

您将收到以下正确结果

ID  IP           Description
--  -----------  -----------
 1  192.168.0.1  router     
 2  192.168.0.2  test server
 3  192.168.0.3  dev server 

答案 1 :(得分:1)

成功的方法将由三部分组成:

  1. 解析IPAddress列并将其拆分为两个逻辑(文本)列:IPAddressLowIPAddressHigh,用于捕获区域的IP范围。我们称之为qryAreas

    select
      [Name]
    , ... as IPAddressLow
    , ... as IPAddressHigh
    from Areas
    
  2. 实现一个函数(在VBA中,然后可以从Access SQL中调用)来对IP地址进行比较。比较器功能可能类似于:

    ' Returns:
    '  -1 if IP1 < IP2
    '   0 if IP1 = IP2
    '   1 if IP1 > IP2
    Function CompareIPAddresses(ip1 As String, ip2 As String) As Integer
      ip1_arr = Split(ip1, ".")
      ip2_arr = Split(ip2, ".")
    
      For i = 0 To 3
        ip1_arr(i) = CLng(ip1_arr(i))
        ip2_arr(i) = CLng(ip2_arr(i))
      Next i
    
      If ip1 = ip2 Then
        retval = 0
      ElseIf ip1_arr(0) < ip2_arr(0) Then
        retval = -1
      ElseIf ip1_arr(0) = ip2_arr(0) And ip1_arr(1) < ip2_arr(1) Then
        retval = -1
      ElseIf ip1_arr(0) = ip2_arr(0) And ip1_arr(1) = ip2_arr(1) And ip1_arr(2) < ip2_arr(2) Then
        retval = -1
      ElseIf ip1_arr(0) = ip2_arr(0) And ip1_arr(1) = ip2_arr(1) And ip1_arr(2) = ip2_arr(2) And ip1_arr(3) < ip2_arr(3) Then
        retval = -1
      Else
        retval = 1
      End If
    
      CompareIPAddresses = retval
    End Function
    
  3. 在查询中使用上述函数来确定IP地址是否等于某个值或是否在某个范围内。例如,如果您有一个地址192.168.1.100并想知道它在哪个区域,您可以这样做:

    select [Name]
    from qryAreas
    where CompareIPAddresses(IPAddressLow, '192.168.1.100') in (-1, 0)
    and CompareIPAddresses('192.168.1.100', IPAddressHigh) in (-1, 0)
    
  4. 这里的where子句是更优雅的where 192.168.1.100 between IPAddressLow and IPAddressHigh语法的笨重等价物,因为你没有本机IP地址数据类型及其相应的运算符 - 所以你滚动你的自己的。