对表中的每一行运行SQL Server函数

对表中的每一行运行SQL Server函数,sql,sql-server,database,tsql,Sql,Sql Server,Database,Tsql,我有一个函数,它迭代表中的“每一行”。当它运行时,它应该查看每一行,拉入该行的相关设置值并运行函数,该函数依次返回结果并用正确的值更新正确的行。它正在运行并返回最后一行的值,并用该值更新所有行。知道我做错了什么吗 SELECT RowNum = ROW_NUMBER() OVER(ORDER BY ID) ,* INTO #Geo FROM DDDG DECLARE @MaxRownum INT SET @MaxRownum = (SELECT MAX(RowNum) F

我有一个函数,它迭代表中的“每一行”。当它运行时,它应该查看每一行,拉入该行的相关设置值并运行函数,该函数依次返回结果并用正确的值更新正确的行。它正在运行并返回最后一行的值,并用该值更新所有行。知道我做错了什么吗

SELECT 
     RowNum = ROW_NUMBER() OVER(ORDER BY ID)
     ,*
INTO #Geo
FROM DDDG

DECLARE @MaxRownum INT
SET @MaxRownum = (SELECT MAX(RowNum) FROM #Geo)

DECLARE @Iter INT
SET @Iter = (SELECT MIN(RowNum) FROM #Geo)

WHILE @Iter <= @MaxRownum
BEGIN
     SELECT *
     FROM #Geo
     WHERE RowNum = @Iter

    DECLARE @address nvarchar (100);
    Select @address =  Ad1 from DDDG where id = @Iter;

    DECLARE @state nvarchar (100);
    SET @state = 'FL';

    DECLARE @zip nvarchar (100);
    SET @zip = '33142';

    DECLARE @city nvarchar (100);
    SET @city = 'Miami';

    DECLARE @nation nvarchar (2);
    SET @nation = 'us';

    DECLARE @g geography;

    WAITFOR DELAY '00:00:00.050'
    SET @g = dbo.Geocode(@nation, @state, @city, @zip, @address);

    Update DDDG 
    Set Lat = @g.Lat 
    where id = @Iter;

    Update DDDG 
    Set long = @g.Long 
    where id = @Iter;

     SET @Iter = @Iter + 1
END

DROP TABLE #Geo

我现在只有一个问题。当我删除行时,RowNum和@Iter不再匹配。除了每次重新创建表之外,还有其他方法解决此问题吗

我可能遗漏了什么,但你为什么需要一个循环呢

UPDATE DDDG
SET Lat     = dbo.GeoCode('us','FL','Miami','33142',Ad1).Lat,
    Long    = dbo.GeoCode('us','FL','Miami','33142',Ad1).Long;
通过将对
dbo.GeoCode
的调用次数减少到每行一次,还可以进一步改进查询:

UPDATE t
SET Lat     = g.GC.Lat,
    Long    = g.GC.Long
FROM DDDG AS t
CROSS APPLY (
    SELECT dbo.GeoCode('us','FL','Miami','33142',Ad1) AS GC
) AS g;
在获得对等方对上述问题的否决票后,修改了查询:

WITH CTE_DDD AS
(
  SELECT * FROM DDD
)
UPDATE CTE_DDD SET lat = (SELECT lat from dbo.Geocode(@nation, @state, @city, @zip,Ad)), long = (SELECT long from    dbo.Geocode(@nation, @state, @city, @zip,Ad))

我同意交叉应用是一个更好的解决方案,因为它会每行调用一次函数

您应该重新编写逻辑以消除循环……SQL是一种基于集合的语言,执行起来非常糟糕。当你放松了线性思维,一个脚本更新所有行,没有循环时,它的处理效果要好得多。你确定Geocode函数并不是只为每个地址返回相同的晶格度和经度吗?我确定(Wily博士的问题),至于更好的方法,我在这方面只做了6个月左右。。如果你能给我一个更好的方法。。。。我完全支持itI,我尝试过,但当以这种方式运行时,它会用文件中的最后一个地址更新所有记录table@user3266908您没有指定一种方法来知道行的最后一个地址。如果缺少条件,此查询将更新整个表,所有记录中只更新最后一个Ad1的lat和long。@DipenduPaul问题中没有
WHERE
条件,op在整个表中循环。User3266908在query.OMG中使用了
WHERE id=@Iter
,这是您最大的问题。这是我一生中见过的最伟大的代码。。我会给你5颗星的我可以。。。这将结束长达数周的搜索。。。。我对所有这些都不熟悉,你推荐给noob的任何网站或书籍?谢谢,很高兴它能帮上忙!W3Schools网站是一个很好的学习基础知识的网站;当然,你会在互联网上看到SQL专家撰写的精彩文章。从连接开始,选择、插入、删除、更新、分组、CTE、row_number()…我最近发现,在类似这样的论坛上活动是一种很好的学习方式,因此我也向您推荐。抱歉,但这是如何工作的?您没有为
Ad1
提供表别名,因此应该会给出一个错误。为什么您需要自己进行
连接
,只需更新table@Lamak,他没有将表自身连接到表中(除非答案已编辑)。他正在定义一个根本不用的CTE。其中d.id=id的
是完全多余的…@ypercube你当然是对的。
id=id
把我甩了,我认为这是一个
JOIN
WITH CTE_DDD(ID,Ad1)
AS
(
  SELECT ID, Ad1 FROM DDD
)
UPDATE d 
SET d.lat = dbo.Geocode(@nation, @state, @city, @zip,Ad1).lat, long = dbo.Geocode(@nation, @state, @city, @zip,Ad1).long 
FROM DDD d 
WHERE d.id = ID
WITH CTE_DDD AS
(
  SELECT * FROM DDD
)
UPDATE CTE_DDD SET lat = (SELECT lat from dbo.Geocode(@nation, @state, @city, @zip,Ad)), long = (SELECT long from    dbo.Geocode(@nation, @state, @city, @zip,Ad))