使用While循环和Between运算符进行查询?

时间:2014-07-02 13:44:26

标签: sql sql-server tsql sql-server-2012 between

我想知道是否有更好的方法来编写此查询,或者我是如何做到的最有效。

我正在浏览已经转换为其表中数字值的IP地址列表。然后,我需要查找地理位置数据(来自MaxMind GeoIp2),其中所选IP地址位于地理位置数据的起始IP和结束IP之间。获得地理位置数据后,我使用地理位置表的ID更新AllIP表。这将允许我稍后加入表格。

你会注意到我在while循环中选择了IP地址的Id,所以我可以通过Id更新记录。这是因为我们可能有多个具有相同值的IP地址。由于我循环遍历所有记录,因此我不想通过数字IP地址值进行更新。

declare @ipcount int
declare @currentCount int
declare @ipAddress bigint
declare @id int
declare @geoCode int
set @currentCount = 0
set @ipcount = (select count(*) from AllIP where Processed = 0)

while @currentCount <=@ipcount
   BEGIN
     set @id = (select top 1 Id from AllIP where Processed = 0)
     set @ipAddress = (select IpAddressNumeric from AllIP where Id = @id)
     set @geoCode  = (
                     SELECT dbo.[GeoLite2-City-Locations].geoname_id
                      FROM
                     dbo.[GeoLite2-City-Blocks2]
                     INNER JOIN dbo.[GeoLite2-City-Locations] ON dbo.[GeoLite2-City-Blocks2].geoname_id = dbo.[GeoLite2-City-Locations].geoname_id
                     Where @ipAddress between dbo.[GeoLite2-City-Blocks2].startIp and dbo.[GeoLite2-City-Blocks2].endIp)

     update AllIP set Processed = 1,geocodeId = @geoCode where Id = @id
     set @currentCount = @currentCount+1
    end

1 个答案:

答案 0 :(得分:4)

看起来整个事情可以用一个UPDATE代替:

UPDATE a
SET Processed = 1, geoCodeId = gcb.geoname_id
FROM
    AllIp a
       inner join
    dbo.[GeoLite2-City-Blocks2] gcb
       on
          a.IpAddressNumeric between gcb.startIp and gcb.endIp
WHERE
    a.Processed = 0

(我已将联接排除在GeoLite2-City-Locations之后,因为您使用的联接列与正在选择的列相同)

通常,您应该更喜欢编写基于集合的代码来处理要在单个语句中更新的所有行,而不是逐行处理(RBAR)。< / p>