Как я могу обновить топ 100 записей на сервере SQL


394

Я хочу обновить первые 100 записей в SQL Server. У меня есть таблица T1с полями F1и F2. T1имеет 200 записей. Я хочу обновить F1поле в топ-100 записей. Как я могу обновить на основе TOP 100в SQL Server?

Ответы:


685

Обратите внимание, скобки необходимы для операторов UPDATE:

update top (100) table1 set field1 = 1

28
Любая идея, как использовать, order byа?
Джо Филлипс

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

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

1
Это отвечает на вопрос «как задано», но ТОП не имеет смысла (и непредсказуемо) без некоторого ЗАКАЗА. Смотрите ответ ниже от Мартина Смита.
Энди Дж

1
кстати: скобки важны!
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тем, что вас интересует, это как "большинство" или "минимум" чего-то. Однако в других случаях вас может заинтересовать только одна подходящая запись. Как я сегодня! Мне нужно было исправить проблемы с данными (циклы) по одному. Весь процесс исправления включал сценарий БД, некоторое вмешательство пользователя и некоторые операции приложения. Нам было все равно, какая запись была обработана первой. Мы просто заботились о том, чтобы обрабатывать их по одному.
MetaFight

17
@MetaFight Но тогда у вас был бы WHEREпункт, чтобы исключить ранее обработанные записи. Вопрос в виде написанного и принятого ответа довольно бессмысленный. Кстати: для использования таблиц в качестве очереди это довольно полезная ссылка
Martin Smith

10
Мне нужно использовать top без порядка, чтобы я мог запустить асинхронный процесс. Предложение where не будет включать те, которые уже были обработаны, но я могу обрабатывать только очень много одновременно. Таким образом, он имеет вполне допустимый вариант использования.
Джефф Дэвис

4
@ Мартин Смит: Допустим, вы хотите обновить в пакетном режиме, скажем, 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.