Як я можу оновити топ-100 записів на сервері sql


393

Я хочу оновити топ-100 записів на SQL Server. У мене є таблиця T1з полями F1і F2. T1має 200 записів. Я хочу оновити F1поле в топ-100 записів. Як я можу оновити на основі TOP 100SQL Server?

Відповіді:


684

Зауважте, що дужки потрібні для операторів UPDATE:

update top (100) table1 set field1 = 1

28
Будь-яка ідея, як використовувати order byтакож?
Джо Філіпс

8
@JoePhilllips Використовуйте відповідь Мартіна Сміта для замовлення
jjxtra

Однак це не 100 найпопулярніших записів, а просто 100 довільно вибраних записів. Топ-100 включав би певний порядок ранжування записів.
Торстен Кеттнер

1
Це дає відповідь на запитання "як задається", але TOP безглуздо (і непередбачувано) без жодного ЗАМОВЛЕННЯ. Відповідь див. Далі Мартін Сміт.
Енді Г

1
btw: круглі дужки важливі!
Simon_Weaver

300

Без ORDER BYцілої ідеї TOPне має великого сенсу. Потрібно мати чітке визначення того, який напрямок "вгору" і який "вниз", щоб концепція верху мала значення.

Тим не менш, SQL Server дозволяє це, але не гарантує детермінованого результату .

UPDATE TOPСинтаксис в загальноприйнятому відповіді не підтримує ORDER BYположення , але можна отримати детерміновану семантику тут за допомогою КТРА або похідною таблиці , щоб визначити потрібний порядок сортування , як показано нижче.

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

71
Ви говорите безглуздо, але це неправда. Я визнаю, що / зазвичай /, коли ви використовуєте TOPшанси, ви повинні використовувати це, ORDER BYтому що те, що вас цікавить, схоже на "найбільше" або "найменше" чогось. В інших випадках, однак, вас може зацікавити лише одна відповідна запис. Як я сьогодні! Мені потрібно було виправляти проблеми (цикли) по одному. Весь процес виправлення включав сценарій db, деяке втручання користувача та деякі операції із застосуванням. Нас не хвилювало, ЯКІ вперше оброблялися записи. Ми просто дбали про те, щоб ми зверталися з ними по черзі.
MetaFight

17
@MetaFight Але тоді у вас був би WHEREпункт про виключення раніше оброблених записів. Питання як письмова та прийнята відповідь є досить безглуздим. BTW: Для використання таблиць у черзі це досить корисне посилання
Мартін Сміт

10
Мені потрібно використовувати топ без замовлення, щоб я міг запустити асинхронний процес. Стаття де не буде включати ті, які вже були оброблені, але я можу обробляти лише стільки за один раз. Таким чином, він має абсолютно правильний випадок використання.
Джефф Девіс

4
@Martin Smith: Скажімо, ви хочете оновити партіями, скажімо, 10000 за один раз. Здається, це корисно для цього, а замовлення не має значення. Як це "не має сенсу"?
Джей Салліван

5
@notfed Це той самий випадок, про який вже говорили на смерть у коментарях вище. Ваш запит у такому випадку не виглядатиме так, як це було у прийнятій відповіді? Вам знадобиться whereзастереження, щоб уникнути опрацювання одних і тих же рядків знову і знову.
Мартін Сміт

14

для тих, як я досі застряг із SQL Server 2000, SET ROWCOUNT {number};можна використовувати перед UPDATEзапитом

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

обмежить оновлення до 100 рядків

Він застарілий принаймні з SQL 2005 року, але станом на SQL 2017 він все ще працює. https://docs.microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017


1
SET ROWCOUNT впливає на тригери, а також на команду, що оновлюється. Якщо у вас встановлено каскадне видалення, воно може провалити транзакцію, якщо в дочірній таблиці існує більше, ніж кількість дочірніх рядків.
EricI

З урахуванням цього, SET ROWCOUNT @RowCountParameter; правильний синтаксис, тоді як SELECT TOP @RowCountParamter * FROM TableName недійсний. Якщо вам потрібно налаштувати рядки, що оновлюються, SET ROWCOUNT # в даний час є кращим варіантом, за умови, що у вас немає дочірніх таблиць з каскадним видаленням.
EricI

У SQL Server 2017 відтепер можна використовувати пункт @variable в TOP: docs.microsoft.com/en-us/sql/t-sql/queries/…
Олександр Зарубкін


4

Що ще крутіше - це той факт, що ви можете використовувати вбудовану функцію з оцінкою таблиці, щоб вибрати, який (і скільки через TOP) рядків (-ів) для оновлення. Це є:

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

Для функції, що оцінюється в таблиці, ви маєте щось цікаве, щоб вибрати рядок для оновлення, наприклад:

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
)

..., і там (на мою скромну думку) криється справжня сила оновлення лише верхньо вибраних рядків детерміновано, одночасно спрощуючи синтаксис UPDATEтвердження.



0

Ви також можете оновити з вибору за допомогою псевдоніму та приєднатися:

UPDATE  TOP (500) T
SET     T.SomeColumn = 'Value'
FROM    SomeTable T
        INNER JOIN OtherTable O ON O.OtherTableFK = T.SomeTablePK
WHERE   T.SomeOtherColumn = 1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.