Run SQL Server function against each row in table

梦想与她 提交于 2020-01-22 03:43:06

问题


I have a function that which iterates "for each row" in the table. When it is run it should look at each row, pull in the related SET values for that row and run the function which in turns returns a result and updates the correct row with the correct value. What is happening is that it is running and returning the value for the very last row and updating all the row with that value. Any ideas what I'm doing wrong?

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

thanks all... I almost got it working.. After a hell of a lot of trial and error I figured out that I needed to change the following

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

I only have one problem now. When I delete rows the RowNum and the @Iter no longer match up. is there a way of fixing this problem other than recreating the table every time?


回答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

Modified Query after getting downvotes from peers for the above one:

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

I would agree that CROSS APPLY is a better solution as it would call the function once per row.




回答2:


I may be missing something, but why do you need a loop at all?:

UPDATE DDDG
SET Lat     = dbo.GeoCode('us','FL','Miami','33142',Ad1).Lat,
    Long    = dbo.GeoCode('us','FL','Miami','33142',Ad1).Long;

It is also possible to improve the query further by reducing the number of calls to dbo.GeoCode to just one per row:

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;


来源:https://stackoverflow.com/questions/21559484/run-sql-server-function-against-each-row-in-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!