views:

317

answers:

5

I'm trying to write a stored procedure in SQL that will :

Make a select query from table1 that will return multiple values Insert new values in table2 (1 new record in table2 for each record returned by the select on table1).

I would use a foreach in C# but I know that SQL doesn't work that way. What's the correct way of doing this?

Thanks!

+8  A: 
INSERT INTO tabl2 (name, id)
   SELECT name, id FROM table1

EDIT

I should add, that loops can indeed be very useful in SQL, so you may want to know how to do that as well. Here's one example:

DECLARE @temp TABLE (ix int identity(1,1), id int, name varchar(100))

INSERT INTO @temp SELECT id, name FROM table1

DECLARE @i int, @max int

SELECT
   @i = 0
   @max = MAX(ix)
FROM
   @temp

WHILE @i < @max
BEGIN
   SET @i = @i + 1

   -- LOGIC HERE...

END
David Hedlund
Nice, but not recommended for large datasets. In that case, using a forward-only cursor would be preferable... even if it makes for ugly code.
Thorarin
you're right about that. +1
David Hedlund
+2  A: 

SQL is a set-based language. What you do is express the result you want as a query - that returns a 'set' which is then inserted into the new table.

You CAN use a CURSOR which is row-by-row based but that really is a last resort. Very very rarely have I found that to be the only way.

maybe if you posted soem more detail about your problem we can help!

n8wrl
Is using cursors a last resort because MS SQL's implementation is slow or is there some other reason?
Hans Malherbe
No, because if you're thinking about cursors early on, you're probably not thinking about the problem in the right way in the first place. Just because you have a tool, doesn't make it the right tool.
clintp
Hans, cursors for iterating through records are generally much slower than a set-based solution especially in SQl Server. Databases are optimized to work in sets not one row at a time, therefore you should only consider a row-by-row solution (cursors, correlated subqueries, etc.) if you cannot find a set-based solution that meets the need. The speed difference may not make a difference in small datasets, but the mindset of looking first for set-based solutions will improve your entire application's performance. Once you are used to them, set-based solutions are easier to write than cursors.
HLGEM
HLGEM nailed it - once you're thinking in sets things really do get easier and perform better.
n8wrl
+1  A: 

You can use a select as the values for an insert

INSERT INTO Table1
(
    FieldA,
    FieldB
)
SELECT
    FieldA,
    FieldB
FROM Table2
blu
+2  A: 

What you want is an insert / select statement, not a for each. If you find yourself needing to iterate over rows to do something, you should be thinking "how can I accomplish the same in a set-based solution." Failure to think set-based when working in SQL can lead you down the path to performance problems very quickly.

INSERT Table2
       (Col1,
        Col2)
SELECT T1Col1,
       T1Col2
FROM   Table1
WHERE  T1Col2 = 'whatever'
Scott Ivey
+1  A: 

No "foreach" needed in this case. For the rare cases that you do, look into cursors and the while-loop. The syntax is so awkward that you'll automatically avoid them if you can :)

For your insert, something like this should do:

INSERT INTO table2 (name, id)
   SELECT name, id FROM table1

(copied for completeness' sake)

Thorarin
yup.. sometimes cursors can be evil. you can also use while to do loops.http://msdn.microsoft.com/en-us/library/ms178642(SQL.90).aspx
pirho
Thanks for the while-loop link. You will need it to read a result set using a cursor :)
Thorarin
In some cases cursors may be faster than while loops and in other cases the while loops may be faster you need to test in your particular situation. In almost all cases (running totals being an exception), a set-based solution is faster than either one, often by quite a bit. I've taken things from over 24 hours to around 40 minutes and from 40+ minutes to 45 seconds by changing from a cursor to a set-based solution. Similar improvements would happen from a while loop to a set-based solution.
HLGEM