2010-06-08 31 views
7

Tôi cần lấy dữ liệu từ một bảng và nhập dữ liệu vào một bảng khác. Trong mã giả, một cái gì đó như thế này:T-SQL cho mỗi giải pháp thay thế?

For Each row in table1 
If row.personid is in table2 then 
    update table2.row 
Else 
    insert row into table2 
End If 
Next 

Cách tốt nhất để làm điều này trong T-SQL là gì? Như tôi đã hiểu, T-SQL không hỗ trợ cho mỗi ..Tiếp theo, vậy tôi có những lựa chọn thay thế nào?

+0

bảng nào có một hàng cho mỗi personid hoặc có thể cùng một id người có nhiều hàng? – Cervo

Trả lời

7

Mọi thứ đều bằng nhau, các hoạt động dựa trên thiết lập sẽ tốt hơn.

update t1 
set t1.x = t2.x 
. 
. 
. 
from table1 t1 
inner join table2 t2 on t1.id = t2.t1id 

then 

insert into table1 
select * from table2 t2 where t2.t1id not in (select table1.id from table1) 
+1

@jvilalta là bạn nói rằng dữ liệu càng lớn thì lý do càng nhiều để lặp qua từng bản ghi? Tôi phải không đồng ý. – Gratzy

+0

Không có lý do nào khác, chỉ việc chèn và cập nhật trong một câu lệnh đặt tất cả trong một giao dịch và nếu tập dữ liệu đủ lớn thì quá trình chuyển mã có thể bị lỗi hoặc sẽ chạy trong một thời gian dài, ngăn các giao dịch khác hoàn thiện. – jvilalta

+0

@jvilalta Tôi chắc rằng nó sẽ không chạy lâu hoặc mất nhiều tài nguyên như lặp qua từng bản ghi. – Gratzy

0

Một trong những cách phổ biến nhất là sử dụng con trỏ. Bằng cách đó, bạn có thể đi qua từng bản ghi mà truy vấn của bạn trả về và xử lý nó cho phù hợp, hoặc với một UPDATE hoặc INSERT.

Xem: http://msdn.microsoft.com/en-us/library/ms180169.aspx

+0

Cảm ơn. Tôi thấy điều này như là một lựa chọn - nhưng cũng đọc rằng điều này là chống lại thực hành tốt nhất b/c con trỏ là không hiệu quả trong quản lý bộ nhớ, vv? – davemackey

+2

@davemackey Bạn đọc chính xác. Tôi không thể tin rằng 2 người đã gợi ý con trỏ cho việc này! –

+1

Đừng bắn sứ giả, Martin. Con trỏ là một phản ứng hợp lý đối với mã giả được đưa ra và không biết thêm thông tin, có thể là một giải pháp hoàn hảo tốt. Nó phụ thuộc vào cách nó sẽ được sử dụng, kích thước bảng, vv .. –

4

Bạn có thể sử dụng con trỏ cho điều này như những người khác đã mô tả. Cá nhân tôi thích thực hiện hai câu lệnh liên tiếp như vậy:

UPDATE tbl2 SET field1=tbl1.field1, field2=tbl1.field2 -- etc. 
FROM tb12 
JOIN tbl1 on tbl2.personid = tbl1.personid 

INSERT tbl2 (personid, field1, field2) 
SELECT personid, field1, field2 
FROM tbl1 
WHERE NOT EXISTS (select personid from tbl2 where personid = tbl1.persondid) 
4

làm điều này trong một vòng lặp while là sai.
cho situatuin của bạn, bạn có thể sử dụng câu lệnh MERGE mới trong máy chủ sql 2008.
Đây là một simple example về cách thực hiện.

3

Bạn nêu TSQL nhưng không đưa ra phiên bản. Nếu bạn đang sử dụng SQL2008, câu lệnh Merge sẽ làm những gì bạn cần.

+0

Cảm ơn, xin lỗi, chúng tôi sử dụng SQL 2008 nhưng một số DB của chúng tôi đang chạy trong chế độ tương thích SQL 2005/2000 (phần mềm kế thừa của bên thứ ba) – davemackey

+0

Nó có thể vẫn hoạt động. Bạn đã thử chưa? Chỉnh sửa: Nó nói ở đây nó được hỗ trợ cho chế độ tương thích SQL 2005 nhưng là im lặng về vấn đề năm 2000! http://msdn.microsoft.com/en-us/library/bb510680.aspx –

4

Nếu bạn đang sử dụng SQL Server 2008 thì cách tốt nhất để thực hiện điều này là với tuyên bố MERGE. Một cái gì đó như ...

MERGE INTO target_table t 
USING source_table s 
ON t.personid = s.personid 
WHEN MATCHED THEN 
    UPDATE ... 
WHEN NOT MATCHED THEN 
    INSERT ... 
9

Nếu bạn đang sử dụng SQL Server 2008 thì bạn có thể sử dụng câu lệnh MERGE. Có thể một cái gì đó như thế này:

MERGE table2 AS t -- target 
USING table1 AS s -- source 
    ON (t.personid = s.personid) 
WHEN MATCHED THEN 
    UPDATE 
    SET second_column = s.second_column, 
     third_column = s.third_column, 
     etc = s.etc 
WHEN NOT MATCHED THEN  
    INSERT (personid, second_column, third_column, etc) 
    VALUES (s.personid, s.second_column, s.third_column, s.etc) 
Các vấn đề liên quan