Допустим, у меня есть следующая простая табличная переменная:
declare @databases table
(
DatabaseID int,
Name varchar(15),
Server varchar(15)
)
-- insert a bunch rows into @databases
Является ли объявление и использование курсора моим единственным вариантом, если я хочу перебирать строки? Есть ли другой способ?
sql-server
tsql
loops
луч
источник
источник
STATIC
опцию, чтобы убрать постоянную повторную проверку базовых таблиц и блокировку, которая существует по умолчанию и заставляет большинство людей ошибочно полагать, что CURSOR - это зло. @JacquesB очень близко: перепроверка, чтобы увидеть, существует ли еще строка результата + проблемы с блокировкой. ИSTATIC
обычно исправляет это :-).Ответы:
Прежде всего, вы должны быть абсолютно уверены, что вам нужно перебирать каждую строку - операции на основе набора будут выполняться быстрее в каждом случае, о котором я могу подумать, и, как правило, использовать более простой код.
В зависимости от ваших данных может быть возможно выполнить цикл, используя только
SELECT
операторы, как показано ниже:Другой альтернативой является использование временной таблицы:
Выбор, который вы должны выбрать, действительно зависит от структуры и объема ваших данных.
Примечание. Если вы используете SQL Server, вам лучше использовать:
Использование
COUNT
будет касаться каждой строки в таблице,EXISTS
единственной нужно касаться первой (см . Ответ Джозефа ниже).источник
STATIC
опцию, которая копирует результирующий набор во временную таблицу, и, следовательно, вы больше не блокируете и не перепроверяете базовые таблицы :-).Просто быстрое примечание, если вы используете SQL Server (2008 и выше), примеры, которые имеют:
Будет лучше обслужен с
Счетчик должен будет коснуться каждой строки в таблице,
EXISTS
нужно только коснуться первой.источник
Вот как я это делаю:
Нет курсоров, нет временных таблиц, нет лишних столбцов. Столбец USERID должен быть уникальным целым числом, как и большинство первичных ключей.
источник
Определите свою временную таблицу следующим образом:
Тогда сделай это -
источник
Вот как я бы это сделал:
[Править] Поскольку я, вероятно, пропустил слово «переменная» при первом прочтении вопроса, вот обновленный ответ ...
источник
Если у вас нет выбора, кроме как идти строка за строкой, создавая курсор FAST_FORWARD. Это будет так же быстро, как создание цикла, и его будет гораздо легче поддерживать в течение длительного времени.
FAST_FORWARD Указывает курсор FORWARD_ONLY, READ_ONLY с включенной оптимизацией производительности. FAST_FORWARD не может быть указан, если также указаны SCROLL или FOR_UPDATE.
источник
FAST_FORWARD
Курсор является прекрасным решением. (upvote)Другой подход без необходимости изменения схемы или использования временных таблиц:
источник
Вы можете использовать цикл while:
источник
Это будет работать в версии SQL SERVER 2012.
источник
Легкий, без необходимости создавать дополнительные таблицы, если у вас есть целое число
ID
на столеисточник
источник
Я действительно не вижу смысла, почему вам нужно прибегать к использованию страшных
cursor
. Но вот еще один вариант, если вы используете SQL Server версии 2005/2008Использовать рекурсию
источник
Я собираюсь предоставить решение на основе множеств.
Это намного быстрее, чем любой метод зацикливания, и его легче писать и поддерживать.
источник
Я предпочитаю использовать Offset Fetch, если у вас есть уникальный идентификатор, который вы можете отсортировать по таблице:
Таким образом, мне не нужно добавлять поля в таблицу или использовать оконную функцию.
источник
Для этого можно использовать курсор:
функция create [dbo] .f_teste_loop возвращает таблицу @tabela (cod int, nome varchar (10)) как начало
конец
создайте процедуру [dbo]. [sp_teste_loop] как начало
конец
источник
Я согласен с предыдущим постом, что основанные на множестве операции, как правило, будут работать лучше, но если вам нужно перебирать строки, вот подход, который я бы выбрал:
Выберите следующую неиспользуемую запись из таблицы и повторите процесс
источник
Шаг 1: Оператор select ниже создает временную таблицу с уникальным номером строки для каждой записи.
Шаг 2: Объявите обязательные переменные
Шаг 3: взять общее количество строк из временной таблицы
Шаг 4: Временная таблица петли, основанная на уникальном номере строки, создается в temp
источник
Этот подход требует только одну переменную и не удаляет строки из @databases. Я знаю, что здесь есть много ответов, но я не вижу такого, который бы использовал MIN, чтобы получить следующий идентификатор, подобный этому.
источник
Вот мое решение, которое использует бесконечный цикл,
BREAK
оператор и@@ROWCOUNT
функцию. Курсоры или временная таблица не нужны, и мне нужно написать только один запрос, чтобы получить следующую строку в@databases
таблице:источник
Это код, который я использую 2008 R2. Этот код, который я использую, предназначен для построения индексов по ключевым полям (SSNO & EMPR_NO) во всех сказках.
источник
было бы лучше:
Избегайте использования SELECT, если вы не ссылаетесь на таблицы, которые просто присваивают значения.
источник