2009-03-17 37 views
37

Lý tưởng nhất là tôi muốn làm điều này:Làm thế nào để cập nhật và trật tự bằng cách sử dụng MS SQL

UPDATE TOP (10) messages SET status=10 WHERE status=0 ORDER BY priority DESC; 

Trong tiếng Anh: Tôi muốn để có được top 10 có sẵn (status = 0) các tin nhắn từ DB và nhốt chúng (trạng thái = 10). Một thông báo có mức độ ưu tiên cao hơn nên được nhận trước tiên.

tiếc là MS SQL không cho phép đơn hàng theo mệnh đề trong bản cập nhật.

Làm cách nào để vượt qua điều này?

Trả lời

37

Bạn có thể làm một subquery nơi bạn lần đầu tiên có được ID của top 10 ra lệnh bằng cách ưu tiên và sau đó cập nhật các shortcut này nằm trên truy vấn phụ:

UPDATE messages 
SET status=10 
WHERE ID in (SELECT TOP (10) Id 
      FROM Table 
      WHERE status=0 
      ORDER BY priority DESC); 
+0

vì tôi muốn có chỉ mục cho giải pháp này. Sau đó tôi sẽ sử dụng: (ưu tiên desc, trạng thái) hoặc (trạng thái, mức ưu tiên desc)? Nói cách khác: là thứ tự được sử dụng trước khi ở đâu? – Toad

+6

Trên thực tế, truy vấn không chính xác .... thứ tự theo mệnh đề không thể được sử dụng trong truy vấn con KHÔNG GIỚI HẠN một TOP cũng được đưa ra. (Đây là những gì công cụ SQL nói). Vì vậy, các truy vấn chính xác nên: UPDATE tin nhắn SET status = 10 WHERE ID trong (SELECT TOP (10) Id TỪ bảng WHERE status = 0 ORDER BY ưu tiên DESC); – Toad

+0

Bạn nói đúng, tôi đã bỏ lỡ đầu khi tôi viết bản chỉnh sửa cuối cùng. Tôi sẽ chỉnh sửa nó như bạn đã nói –

84
WITH q AS 
     (
     SELECT TOP 10 * 
     FROM messages 
     WHERE status = 0 
     ORDER BY 
       priority DESC 
     ) 
UPDATE q 
SET  status = 10 
+2

+1 cho CTE, thực hiện theo cách này sẽ loại bỏ sự tham gia của tôi khi sử dụng mệnh đề OUTPUT – nitzmahone

+4

Đây thực sự là câu trả lời ưu tiên thay vì câu trả lời được chấp nhận. – Carvellis

+0

Hãy nhớ rằng hai câu lệnh không phải là nguyên tử. – Haroon

0

Như đã nêu trong ý kiến ​​dưới đây, bạn cũng có thể sử dụng mệnh đề SET ROWCOUNT, nhưng chỉ cho SQL Server 2014 trở lên.

SET ROWCOUNT 10 

UPDATE messages 
SET status = 10 
WHERE status = 0 

SET ROWCOUNT 0 

Thông tin thêm: http://msdn.microsoft.com/en-us/library/ms188774.aspx

Hoặc với một bảng temp

DECLARE @t TABLE (id INT) 
INSERT @t (id) 
SELECT TOP 10 id 
FROM messages 
WHERE status = 0 
ORDER BY priority DESC 

UPDATE messages 
SET status = 10 
WHERE id IN (SELECT id FROM @t) 
+4

Đối với những người đọc này xa trở lại .. (bạn không bao giờ biết.) SET ROWCOUNT đang đối mặt với sự phản đối http: // msdn.microsoft.com/en-us/library/ms188774.aspx "Sử dụng SET ROWCOUNT sẽ không ảnh hưởng đến các câu lệnh DELETE, INSERT và UPDATE trong bản phát hành SQL Server trong tương lai". - nó tốt lên đến SQL Server 2014 mặc dù ít nhất. –

+0

Trong khi 'rowcount' hoạt động tốt nếu bạn muốn 10 hàng tùy ý, bạn không thể chỉ định' order by' để quyết định chính xác 10. Ví dụ của bạn với bảng tạm thời hoạt động, nhưng nó dựa trên cột id. –

1
UPDATE messages SET 
status=10 
WHERE ID in (SELECT TOP (10) Id FROM Table WHERE status=0 ORDER BY priority DESC); 
2

tôi phải cung cấp này như một cách tiếp cận tốt hơn - bạn không phải lúc nào cũng có sự sang trọng của một trường nhận dạng:

UPDATE m 
SET [status]=10 
FROM (
    Select TOP (10) * 
    FROM messages 
    WHERE [status]=0 
    ORDER BY [priority] DESC 
) m 

Bạn cũng có thể làm cho truy vấn phụ phức tạp như bạn muốn - tham gia nhiều bảng, v.v ...

Tại sao điều này lại tốt hơn? Nó không dựa vào sự hiện diện của một trường nhận dạng (hoặc bất kỳ cột duy nhất nào khác) trong bảng messages. Nó có thể được sử dụng để cập nhật N hàng đầu từ bất kỳ bảng nào, ngay cả khi bảng đó không có khóa duy nhất nào cả.

+0

Câu trả lời này khác với câu trả lời của dotjoe như thế nào: http://stackoverflow.com/a/655561/2279200 – Athafoud

+1

Tôi không ngạc nhiên bởi sự bỏ phiếu xuống trong câu trả lời của tôi nếu bạn không dành thời gian để cố gắng hiểu nó. Câu trả lời của tôi khác với câu trả lời của dotjoe - và hầu hết các câu trả lời khác ở đây - bởi vì các câu trả lời khác cho rằng bảng có một trường nhận dạng (... trong đó ID IN ...). Bạn không thể luôn luôn giả định rằng bảng sẽ có một trường nhận dạng. Tôi cung cấp một thay thế cho khi bạn không có trường ID trong bảng của bạn. Hãy cố gắng hiểu câu trả lời trước khi bỏ phiếu xuống. – mfascino

+0

Cảm ơn bạn đã giải thích ngắn gọn. Vui lòng dành chút thời gian để chỉnh sửa câu trả lời của bạn và thêm chi tiết bạn vừa đề cập. Nó sẽ làm cho câu trả lời của bạn hoàn chỉnh hơn và dễ hiểu hơn mà không tốn quá nhiều thời gian cho nó. Khi bạn chỉnh sửa câu trả lời của mình, tôi sẽ thu hồi phiếu bầu của tôi. – Athafoud

Các vấn đề liên quan