Làm cách nào tôi có thể cập nhật 100 bản ghi hàng đầu trong máy chủ sql


393

Tôi muốn cập nhật 100 bản ghi hàng đầu trong SQL Server. Tôi có một bảng T1với các lĩnh vực F1F2. T1có 200 hồ sơ. Tôi muốn cập nhật các F1lĩnh vực trong 100 hồ sơ hàng đầu. Làm cách nào để cập nhật dựa trên TOP 100SQL Server?

Câu trả lời:


684

Lưu ý, các dấu ngoặc đơn là bắt buộc cho các câu lệnh CẬP NHẬT:

update top (100) table1 set field1 = 1

28
Bất kỳ ý tưởng làm thế nào để sử dụng order bylà tốt?
Joe Phillips

8
@JoePhilllips Sử dụng câu trả lời của Martin Smith cho đơn hàng của
jjxtra

Tuy nhiên, đây không phải là 100 bản ghi hàng đầu, mà chỉ đơn giản là 100 bản ghi được chọn tùy ý. Top 100 sẽ bao gồm một số thứ tự để xếp hạng các hồ sơ.
Thorsten Kettner

1
Điều này trả lời câu hỏi "như đã hỏi" nhưng TOP là vô nghĩa (và không thể đoán trước) mà không có ĐẶT HÀNG. Xem câu trả lời tiếp theo của Martin Smith.
Andy G

1
btw: dấu ngoặc đơn rất quan trọng!
Simon_Weaver

300

Không có ORDER BYtoàn bộ ý tưởng TOPkhông có ý nghĩa nhiều. Bạn cần có một định nghĩa nhất quán về hướng nào là "lên" và hướng nào là "xuống" để khái niệm đỉnh có ý nghĩa.

Tuy nhiên, SQL Server cho phép nhưng không đảm bảo kết quả xác định .

Các UPDATE TOPcú pháp trong câu trả lời được chấp nhận không hỗ trợ một ORDER BYkhoản nhưng nó có thể để có được ngữ nghĩa xác định ở đây bằng cách sử dụng một CTE hoặc bảng nguồn gốc để xác định thứ tự sắp xếp mong muốn như dưới đây.

;WITH CTE AS 
( 
SELECT TOP 100 * 
FROM T1 
ORDER BY F2 
) 
UPDATE CTE SET F1='foo'

71
Bạn nói vô nghĩa nhưng điều đó không đúng. Tôi thừa nhận rằng, / thông thường /, khi bạn sử dụng TOPtỷ lệ cược là bạn nên sử dụng nó ORDER BYbởi vì những gì bạn quan tâm giống như "nhất" hoặc "ít nhất" của một cái gì đó. Tuy nhiên, trong các trường hợp khác, bạn chỉ có thể quan tâm đến việc nhận một bản ghi khớp. Giống như tôi hôm nay! Tôi cần sửa từng vấn đề dữ liệu (chu kỳ) một lần. Toàn bộ quá trình sửa lỗi bao gồm một tập lệnh db, một số can thiệp của người dùng và một số hoạt động của ứng dụng. Chúng tôi không quan tâm hồ sơ WHICH đã được xử lý đầu tiên. Chúng tôi chỉ quan tâm rằng chúng tôi đã xử lý chúng cùng một lúc.
MetaFight

17
@MetaFight Nhưng sau đó bạn sẽ có một WHEREđiều khoản để loại trừ các hồ sơ được xử lý trước đó. Câu hỏi như được viết và chấp nhận câu trả lời là khá vô nghĩa. BTW: Để sử dụng các bảng làm hàng đợi, đây là một liên kết khá hữu ích
Martin Smith

10
Tôi cần sử dụng hàng đầu mà không cần đặt hàng để tôi có thể chạy quy trình không đồng bộ. Mệnh đề where sẽ không bao gồm những mệnh đề đã được xử lý, nhưng tôi chỉ có thể xử lý rất nhiều lần. Vì vậy, nó có một trường hợp sử dụng hoàn toàn hợp lệ.
Jeff Davis

4
@Martin Smith: Giả sử bạn muốn cập nhật theo đợt, hãy nói 10000 mỗi lần. Có vẻ như một cách sử dụng tốt cho việc này, và thứ tự không thành vấn đề. Làm thế nào điều này "không có ý nghĩa"?
Jay Sullivan

5
@notfed Đây là trường hợp tương tự như đã được thảo luận cho đến chết trong các ý kiến ​​trên. Truy vấn của bạn trong trường hợp đó sẽ không giống như câu trả lời được chấp nhận phải không? Bạn sẽ cần một wheremệnh đề để tránh xử lý các hàng giống nhau nhiều lần.
Martin Smith

14

đối với những người như tôi vẫn bị mắc kẹt với SQL Server 2000, SET ROWCOUNT {number};có thể được sử dụng trước khi UPDATEtruy vấn

SET ROWCOUNT 100;
UPDATE Table SET ..;
SET ROWCOUNT 0;

sẽ giới hạn cập nhật xuống 100 hàng

Nó đã bị từ chối ít nhất kể từ SQL 2005, nhưng kể từ SQL 2017, nó vẫn hoạt động. https://docs.microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017


1
SET ROWCOUNT ảnh hưởng đến các kích hoạt cũng như lệnh được cập nhật. Nếu bạn đã thiết lập xóa tầng, nó có thể thất bại trong giao dịch nếu có nhiều hơn hàng của các hàng con tồn tại trong bảng con.
EricI

Như đã nói, SET ROWCOUNT @RowCountParameter; là cú pháp hợp lệ, trong khi CHỌN TOP @RowCountParamter * TỪ Tên bảng không hợp lệ. Nếu bạn cần định cấu hình các hàng đang được cập nhật, SET ROWCOUNT # hiện là tùy chọn tốt hơn, miễn là bạn không bật bảng con với chức năng xóa tầng.
EricI

Trong SQL Server 2017, giờ đây có thể sử dụng @variable trong mệnh đề TOP: docs.microsoft.com/en-us/sql/t-sql/queries/ trộm
Alexandr Zarubkin

13
update tb set  f1=1 where id in (select top 100 id from tb where f1=0)

4

Điều thú vị hơn nữa là bạn có thể sử dụng Hàm Bảng giá trị nội tuyến để chọn hàng (và số lượng qua TOP) hàng để cập nhật. Đó là:

UPDATE MyTable
SET Column1=@Value1
FROM tvfSelectLatestRowOfMyTableMatchingCriteria(@Param1,@Param2,@Param3)

Đối với hàm có giá trị bảng, bạn có một cái gì đó thú vị để chọn hàng để cập nhật như:

CREATE FUNCTION tvfSelectLatestRowOfMyTableMatchingCriteria
(
    @Param1 INT,
    @Param2 INT,
    @Param3 INT
)
RETURNS TABLE AS RETURN
(
    SELECT TOP(1) MyTable.*
    FROM MyTable
    JOIN MyOtherTable
      ON ...
    JOIN WhoKnowsWhatElse
      ON ...
    WHERE MyTable.SomeColumn=@Param1 AND ...
    ORDER BY MyTable.SomeDate DESC
)

..., và có những lời nói dối (theo ý kiến ​​khiêm tốn của tôi) sức mạnh thực sự của việc chỉ cập nhật các hàng được chọn hàng đầu một cách xác định đồng thời đơn giản hóa cú pháp của UPDATEcâu lệnh.


0

Thử:

UPDATE Dispatch_Post
SET isSync = 1
WHERE ChallanNo 
IN (SELECT TOP 1000 ChallanNo FROM dbo.Dispatch_Post ORDER BY 
CreatedDate DESC)

0

Bạn cũng có thể cập nhật từ lựa chọn bằng cách sử dụng bí danh và tham gia:

UPDATE  TOP (500) T
SET     T.SomeColumn = 'Value'
FROM    SomeTable T
        INNER JOIN OtherTable O ON O.OtherTableFK = T.SomeTablePK
WHERE   T.SomeOtherColumn = 1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.