Ms sql цикл: MS SQL Server и T-SQL

Цикл · Loginom Help

Компонент может применяться для циклического исполнения выбранного пользователем узла. В качестве такого узла, как правило, используется Подмодель, в которой задаются действия выполняемые над данными в каждой итерации. Возможны следующие способы задать итерации цикла:

  1. Заданное количество раз — аналог «FOR … TO …».
  2. Количество итераций задается условием выхода из цикла — аналог «DO … WHILE …». На предмет соответствия этому условию анализируется значение выходной переменной узла, заключенного в цикл.
  3. Количество итераций задается количеством групп, на которые разделяются строки входного набора данных — аналог «FOR EACH». В предельном случае количество итераций равно количеству строк входного набора.

В первом и втором случае применение входного набора данных не обязательно. Но, если таковой применяется, то в каждой итерации на вход узла, заключенного в цикл, подаются все строки этого набора (наборов).

В третьем случае строки входного набора разделяются по заданному признаку на группы строк, и в каждой итерации на вход узла, заключенного в цикл, подаются строки очередной группы. Если в качестве признака группы указываются уникальные идентификаторы строк входного набора, то такая группа будет содержать только одну строку. В этом случае цикл будет перебирать строки входного набора и передавать очередную строку на вход узла, заключенного в цикл.

Курсоры в MSSQL — перебор выборки в цикле.


  • Новые

  • Лучшие

  • Все
Курсоры в MSSQL — перебор выборки в цикле.

MS SQL — по необходимости

    Команды манипулирования данными SELECT, UPDATE, DELETE работают сразу с группами строк. Эти группы, вплоть до отдельных строк, можно выбрать с помощью опции WHERE. А если надо перебрать строки некоторой таблицы последовательно, одну за другой? На этот случай в языке SQL существуют курсоры. Курсор (current set of record) – временный набор строк, которые можно перебирать последовательно, с первой до последней.

При работе с курсорами используются следующие команды.

    Объявление курсора:
DECLARE имя_курсора CURSOR FOR SELECT текст_запроса

Любой курсор создается на основе некоторого оператора SELECT.

Открытие курсора:
OPEN имя_курсора

Для того чтобы с помощью курсора можно было читать строки, его надо обязательно открыть.

Чтение следующей строки из курсора:
FETCH имя_курсора INTO список_переменных

Переменные в списке должны быть в том же количестве и того е типа, что и столбцы курсора.

Глобальная переменная @@FETCH_STATUS принимает ненулевое значение, если строк в курсоре больше нет. Если же набор строк еще не исчерпан, то @@FETCH_STATUS равна нулю, и оператор FETCH перепишет значения полей из текущей строки в переменные.

Закрытие курсора:
CLOSE имя_курсора

Для удаления курсора из памяти используется команда
DEALLOCATE имя_курсора

Для иллюстрации использования курсора создадим процедуру, которая будет выбирать данные из одной таблицы, перебирать их в курсоре анализируя, есть ли такие данные во второй таблице и вставлять в третью таблицу, если данные записи удовлетворяют определённым критериям.

CREATE PROCEDURE [dbo].[MyProcedure] AS

DECLARE	@ID INT
DECLARE 	@QUA INT
DECLARE	@VAL VARCHAR (500)
DECLARE	@NAM VARCHAR (500)
/*Объявляем курсор*/
DECLARE @CURSOR CURSOR
/*Заполняем курсор*/
SET @CURSOR  = CURSOR SCROLL
FOR
SELECT  INDEX, QUANTITY, VALUE,  NAME  
  FROM  My_First_Table WHERE  QUANTITY > 1
/*Открываем курсор*/
OPEN @CURSOR
/*Выбираем первую строку*/
FETCH NEXT FROM @CURSOR INTO @ID, @QUA, @VAL, @NAM
/*Выполняем в цикле перебор строк*/
WHILE @@FETCH_STATUS = 0
BEGIN

 	IF NOT EXISTS(SELECT VAL FROM My_Second_Table WHERE ID=@ID)
	BEGIN
/*Вставляем параметры в третью таблицу если условие соблюдается*/
		INSERT INTO My_Third_Table (VALUE, NAME) VALUE(@VAL, @NAM)
	END
/*Выбираем следующую строку*/
FETCH NEXT FROM @CURSOR INTO @ID, @QUA, @VAL, @NAM
END
CLOSE @CURSOR


Вот собственно и всё.



MSSQL
курсоры


  • Популярное

Установка русской кодировки на уже созданную базу данных (смена COLLATION)

Полезный пример изменения кодировки (COLLATION) на уже созданной базе данных. В данном примере устан (читать далее…)


404  


Чистка логов базы данных MSSQL

Вообще процесс чистки логов должен проходить планово, и следить за этим и настраивать должен професс (читать далее…)


139  


MSSQL — передача таблицы или списка значений в процедуру ( C# .NET )

Часто бывает необходимость передать за один раз некоторый набор данных в процедуру, в этой публикаци (читать далее…)


107  


Пример MERGE в MSSQL T-SQL

Простой пример MERGE для TSQL. В примере подразумевается, что мы оперируем двумя одинаковыми по стру (читать далее. ..)


99  


OFFSET FETCH пример применения в TSQL

Фильтр OFFSET FETCH в языке TSQL интересен тем что в отличии от фильтра TOP позволяет пропускать зад (читать далее…)


80  

SQL Server ДЛЯ КАЖДОГО цикла

У меня есть следующий SQL-запрос:

 DECLARE @MyVar datetime = '1/1/2010'
ВЫБЕРИТЕ @MyVar
 

Это, естественно, возвращает «01.01.2010».

Я хочу получить список дат, скажем:

 1/1/2010
01.02.2010
01.03.2010
01.04.2010
01.05.2010
 

Затем я хочу ДЛЯ КАЖДОГО через числа и запустить SQL-запрос.

Что-то вроде (псевдокод):

 Список = 1/1/2010,2/1/2010,3/1/2010,4/1/2010,5/1/2010
Для каждого x в списке
делать
  ОБЪЯВИТЬ @MyVar datetime = x
  ВЫБЕРИТЕ @MyVar
 

Таким образом, это вернет:-

01. 01.2010
01.02.2010
01.03.2010
01.04.2010
01.05.2010

Я хочу, чтобы это возвращало данные в виде одного набора результатов, а не нескольких наборов результатов, поэтому мне может понадобиться использовать какое-то объединение в конце запроса, поэтому каждая итерация цикла объединяется со следующей.

изменить

У меня есть большой запрос, который принимает параметр «дата», мне нужно запустить его 24 раза, каждый раз с определенной датой, которую я должен иметь возможность предоставить (эти даты будут быть динамичным) Я хочу избежать повторения моего запроса 24 раза с присоединением к ним всех объединений, как если бы мне нужно было вернуться и добавить дополнительные столбцы, это заняло бы очень много времени.

  • sql
  • sql-сервер
  • tsql

3

SQL в первую очередь является языком, ориентированным на наборы данных, поэтому использовать в нем цикл — плохая идея.

В этом случае аналогичный результат может быть достигнут с помощью рекурсивного CTE:

 с cte как
(выбрать 1 я объединить все
 выберите i+1 i из cte, где i < 5)
выберите dateadd(d, i-1, '2010-01-01') из cte
 

4

Вот вариант с табличной переменной:

 DECLARE @MyVar TABLE(Val DATETIME)
DECLARE @I INT, @StartDate DATETIME
УСТАНОВИТЬ @I = 1
УСТАНОВИТЕ @StartDate = '20100101'
ПОКА @I <= 5
НАЧИНАТЬ
    ВСТАВЬТЕ В @MyVar(Val)
    ЗНАЧЕНИЯ(@StartDate)
    УСТАНОВИТЬ @StartDate = DATEADD (ДЕНЬ, 1, @ StartDate)
    НАБОР @I = @I + 1
КОНЕЦ
ВЫБИРАТЬ *
ОТ @MyVar
 

То же самое можно сделать с временной таблицей:

 CREATE TABLE #MyVar(Val DATETIME)
DECLARE @I INT, @StartDate DATETIME
УСТАНОВИТЬ @I = 1
УСТАНОВИТЕ @StartDate = '20100101'
ПОКА @I <= 5
НАЧИНАТЬ
    ВСТАВИТЬ В #MyVar(Val)
    ЗНАЧЕНИЯ(@StartDate)
    УСТАНОВИТЬ @StartDate = DATEADD (ДЕНЬ, 1, @ StartDate)
    НАБОР @I = @I + 1
КОНЕЦ
ВЫБИРАТЬ *
ОТ #MyVar
 

Вы должны сказать нам, какова ваша основная цель, как сказал @JohnFx, это, вероятно, можно было бы сделать другим (более эффективным) способом.

3

Вы можете использовать таблицу переменных, например:

 объявлять @num int
установить @num = 1
объявить таблицу @results ( val int )
в то время как (@число < 6)
начинать
  вставить в @results ( val ) значения ( @num )
  установить @num = @num + 1
конец
выберите val из @results
 

0

Это зависит от того, что вы хотите сделать с результатами. Если вам нужны только числа, вариантом на основе набора будет таблица чисел, которая пригодится для самых разных вещей.

Для MSSQL 2005+ вы можете использовать рекурсивное CTE для создания встроенной таблицы чисел:

 ;WITH Numbers (N) AS (
    ВЫБЕРИТЕ 1 ОБЪЕДИНЕНИЕ ВСЕХ
    ВЫБЕРИТЕ 1 + N ИЗ Чисел, ГДЕ N < 500
)
ВЫБРАТЬ N ИЗ Чисел
ОПЦИЯ (МАКСРЕКУРСИЯ 500)
 

4

 объявить @counter как int
установить @счетчик = 0
объявить @date как varchar(50)
установить @date = cast(1+@counter as varchar)+'/01/2013'
пока(@счетчик < 12)
начинать
выберите cast(1+@counter as varchar)+'/01/2013' в качестве даты
установить @counter = @counter + 1
конец
 

Конечно старый вопрос. Но у меня есть простое решение, в котором нет необходимости в циклах, CTE, табличных переменных и т. д.

 DECLARE @MyVar datetime = '1/1/2010'
ВЫБЕРИТЕ @MyVar
ВЫБЕРИТЕ ДАТУДОБАВИТЬ (ДД,ЧИСЛО,@MyVar)
ИЗ master.dbo.spt_values
ГДЕ TYPE='P' И ЧИСЛО ОТ 0 ДО 4
ЗАКАЗАТЬ ПО НОМЕРУ
 

Примечание: spt_values ​​ — это недокументированная таблица Microsoft. У него есть номера для каждого типа. Его не рекомендуется использовать, так как он может быть удален в любых новых версиях сервера sql без предварительной информации, поскольку он недокументирован. Но мы можем использовать его как быстрый обходной путь в некоторых сценариях, подобных приведенным выше.

1

 [СОЗДАТЬ ПРОЦЕДУРУ [rat].[GetYear]
КАК
НАЧИНАТЬ
-- переменная для хранения даты начала
Объявить @StartYear как int
-- Переменная для конечной даты
Объявить @EndYear как int
-- Установка значения в strat Date
выберите @StartYear = значение из rat.Configuration, где имя = 'REPORT_START_YEAR';
-- Установка конечной даты
выберите @EndYear = значение из rat. Configuration, где имя = 'REPORT_END_YEAR';
-- Создание таблицы тем
    с [Годы] как
    (
        --Выбор года
        выберите @StartYear [Год]
        --делаю союз
        союз всех
         -- делаем цикл в таблице Years
         выберите Год+1 Год из [Годы], где Год < @EndYear
     )
    --Выбор таблицы Год
выбор]
 

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя адрес электронной почты и пароль

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Цикл Microsoft SQL - Неправильная итерация для меня - Вопросы

chadgriff


1

Я пытаюсь ежедневно обновлять количество попыток отправки электронной почты в моей базе данных Microsoft SQL. Я построил следующий рабочий процесс, и он повторяется, как и ожидалось. Однако выходные данные узла «Попытки обновления электронной почты» используют данные из первого элемента для каждого выполнения. Следовательно, обновляется только одна запись в базе данных… и она обновляется несколько раз с данными в зависимости от общего количества событий, возвращенных из узла «Получить завершенные события».

Пример завершенных событий в формате JSON выглядит так:

 [
  {
    "recordId": 43,
    "eventName": "Старое событие 2",
    "eventlocation": "Стадион УГА",
    "eventDate": "02.12.2021",
    "Попытки электронной почты": 1,
    "userEmail": "любой@gmail.com"
  },
  {
    "recordId": 44,
    "eventName": "Участники теста 1",
    "eventlocation": "Кто знает",
    "eventDate": "07.12.2021",
    "Попытки электронной почты": 0,
    "userEmail": "любой@gmail. com"
  },
  {
    "recordId": 61,
    "eventName": "космос",
    "eventlocation": "самый внешний край",
    "eventDate": "05.12.2021",
    "Попытки электронной почты": 0,
    "userEmail": "любой@gmail.com"
  }
]
 

Ожидаемым результатом будет обновление каждой из отдельных записей (идентифицируемых их recordId) соответствующими вычислениями (увеличенными на 1 по сравнению с их существующим значением). В настоящее время, если возвращаются три события, для первого события количество попыток отправки электронной почты увеличивается на 1 (и новое значение записывается столько раз, сколько существует событий/пакетов).

Будем признательны за любые указания относительно того, что мне не хватает.

Джон


2

Эй, @chadgriff,

Похоже, вы используете вывод узла до разделения на пакеты. Если вместо этого вы используете вывод узла разделения, он должен дать вам то, что вам нужно.

чадгрифф


3

@Jon,

Спасибо за быстрый ответ. Однако я не уверен, что понял ваш ответ. Если я установлю рабочий процесс в соответствии с тем, что, как я думаю, вы говорите, я получу бесконечный цикл. Это то, что вы имели в виду?

В выходных данных узла SplitInBatches было только 3 элемента. Я вручную остановил рабочий процесс после 25 итераций.

Пожалуйста, поясните… спасибо!

Джон


4

Hey @chadgriff,

В исходном рабочем процессе перейдите к запросу обновления SQL и измените {{$node["Retrieve Completed Events"].