One thing I've learned while using SQL Server is (whenever possible), perform as much as you can on the server. That means either stored procedures or SQL commands passed up to the server. It also means thinking about problems as sets, as opposed to a more procedural approach. Visual FoxPro makes it easy to blur the lines between SQL commands and normal procedural code (mixing and matching as you'd like), so you tend to start getting locked into thinking about data on those terms. While some of this translates directly to SQL Server (obviously, the SQL language itself), other things don't.
I recently decided to add a new foreign key to a table; the structural specifics aren't particularly important so I won't go into too much detail about them. Essentially, I had a parent (A) and child table (B). There is a posting process which takes a snapshot (C) of some or all of the records in the child table for a specific parent. This snapshot includes a foreign key back to the original child record but didn't include a foreign key back to the parent (since it could be derived by joining to this child table). I began to realize that, because of the number of records involved (it could be as many as 250,000 records in the child (B) for a single parent record (A), which meant up to 250,000 records in our snapshot table) that most of the queries were really slow because of the extra hop involved in resolving this parent key. So, I decided to go ahead and add a foreign key into the snapshot table (C) to the parent (A). That also meant I needed to go back and fill in the new foreign key in the Snapshot (C) table.
In VFP, you might just open the tables, SCAN through the Snapshot (C) table, do a SEEK into the Child (B) table for the foreign key back to the Parent (A) table and save it into the Snapshot (C) table. That works OK if the tables are local, what about with SQL Server? I guess you could take the same approach; pull a copy of the records from the Snapshot (C) and Child (B) tables locally, index them, then run through the same SCAN loop (or if you're really old school, set a relation and just do a REPLACE). But how long will that take - remember we're talking about pulling down up to 250,000 records in the Child (B) table, plus another 250,000 records from the Snapshot (C) table, then updating all of the records in Snapshot (C) table. Multiply that by the number of master records (in my case, only 20-30 of the master records had anywhere near 250,000 records but we're still talking millions of records).
Suddenly the above approach doesn't look like such a good idea. Thankfully, SQL includes provisions in the UPDATE command to do exactly what I wanted to. It would still take a while to run (I clocked it around 25 minutes), but it was a significantly better solution than a SCAN loop. Here's what the query ends up looking like:
UPDATE Snapshot SET Snapshot.fk_Parent = Child.fk_Parent FROM ChildINNER JOIN Snapshot ON Snapshot.fk_Child = Child.PrimaryKey
So what does this actually mean? We're basically saying, inside of our Snapshot (C) table set our new foreign key equal to the Parent (A) foreign key in the Child (B) table. The FROM/INNER JOIN defines how to match the record in the Snapshot (C) to the one in Child (B). Simple and fast.