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

时间:2014-02-04 17:36:47

标签: sql sql-server database tsql

我有一个函数,它迭代“表中的每一行”。当它运行时,它应该查看每一行,拉入该行的相关SET值并运行该函数,该函数依次返回结果并使用正确的值更新正确的行。发生的事情是它正在运行并返回最后一行的值并使用该值更新所有行。我有什么想法我做错了吗?

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

更新.....

感谢所有人...我几乎让它工作了......经过大量的试验和错误之后,我发现我需要更改以下内容

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

我现在只有一个问题。当我删除行时,RowNum和@Iter不再匹配。有没有办法解决这个问题,除了每次重新创建表格?

2 个答案:

答案 0 :(得分:7)

我可能会遗漏一些东西,但为什么你需要一个循环?:

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;

答案 1 :(得分:1)

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))

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