Форум программистов, компьютерный форум, киберфорум
Microsoft SQL Server
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/40: Рейтинг темы: голосов - 40, средняя оценка - 4.55
5 / 5 / 4
Регистрация: 24.03.2010
Сообщений: 241
Записей в блоге: 1
1

Цикл внутри цикла (While)

21.01.2018, 13:27. Показов 7259. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет.

Никак не получается организовать цикл внутри цикла на SQL Server 2012. В итоге отрабатывает только первый цикл.

На вход подаю:

А) количество исходных строк, например, 10 позиций.
Б) В таблице T001W 314 записей.

В итоге, при завершении работы кода, таблице @lt_marc должно быть 314 * 10 = 3140 записей, то есть, 314 записей для 1, далее 314 записей для 2 и так далее до 3140.

Привожу код:

T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
declare @lv_max_t001w integer
declare @lv_min_t001w integer
declare @lv_t001w NVARCHAR(4)
 
declare @lv_pfach nvarchar(1)
 
declare @lv_max_rec bigint
declare @lv_min_rec integer
 
DECLARE @lt_marc TABLE (id int identity, MATNR nvarchar(18), WERKS nvarchar(4));
 
SELECT  @lv_max_t001w = max(IDT001W) FROM T001W -- определяем кол-во записей в табл T001W
set  @lv_min_t001w = 1
 
set @lv_max_rec = 10 -- необходимое кол-во озм, которые должны быть растиражированы на каждую запись в T001W
set @lv_min_rec = 1 -- начальное для цикла значение
 
WHILE  @lv_min_rec <= @lv_max_rec 
    BEGIN
    SET NOCOUNT ON
 
    WHILE @lv_min_t001w <= @lv_max_t001w
 
                BEGIN
                    SELECT @lv_t001w = werks, @lv_pfach = pfach FROM t001w where idt001w = @lv_min_t001w
 
                    ----if  @lv_pfach = '' -- если испрользуется, то вставляем
                    ----    begin
                            INSERT INTO @lt_marc (MATNR, WERKS) VALUES (@lv_min_rec, @lv_t001w)
                    ------end
 
                    set @lv_min_t001w = @lv_min_t001w + 1
                END
 
            set @lv_min_rec = @lv_min_rec + 1
        
    END
 
    select * from @lt_marc
На финише, в таблице @lt_marc у меня появляются только 314 строк, в место 3140.

Что не так делаю? Почему при завершении самого первого цикла, кол не идет для обработки set @lv_min_rec = @lv_min_rec + 1 ?

Подскажите, пожалуйста.

Всем спасибо заранее!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.01.2018, 13:27
Ответы с готовыми решениями:

Цикл For. Вывод цикла внутри цикла
Всем привет, есть проблемка. Код рабочий но при вводе среднего бала допустим выше несуществующего...

Цикл внутри цикла
Здравствуйте, делаю скрипт для массового добавления урлов и кеев в базу тдс. Нужно чтобы переменная...

Цикл внутри цикла
Есть вопрос, можно ли задать цикл внутри цикла? Вот в этой программе чтоб j прошёл условие...

Цикл внутри цикла!
Здравствуйте. Имеется БД из 2 таблиц. Подключена к программе через АДО. Нужно вывести отчет в...

12
3462 / 2473 / 695
Регистрация: 02.08.2011
Сообщений: 6,704
21.01.2018, 13:37 2
WHILE @lv_min_t001w <= @lv_max_t001w
После прохода по внутреннему циклу вы не сбрасываете значения переменных.

Добавлено через 4 минуты
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SELECT  @lv_max_t001w = MAX(IDT001W) FROM T001W -- определяем кол-во записей в табл T001W
SET  @lv_min_t001w = 1;
DECLARE @ly_maxCurrent INTEGER; 
DECLARE @ly_minCurrent INTEGER;
/ *во внешнем цикле */
..
 
SET @ly_maxCurrent = @lv_max_t001w;
SET @ly_minCurrent = @lv_min_t001w;
 
WHILE @ly_minCurrent <= @ly_maxCurrent
 
                BEGIN
                    SELECT @lv_t001w = werks, @lv_pfach = pfach FROM t001w WHERE idt001w = @lv_min_t001w
 
                    ----if  @lv_pfach = '' -- если испрользуется, то вставляем
                    ----    begin
                            INSERT INTO @lt_marc (MATNR, WERKS) VALUES (@lv_min_rec, @lv_t001w)
                    ------end
 
                    SET @lv_min_t001w = @lv_min_t001w + 1
                END
 
            SET @ly_minCurrent = @ly_minCurrent + 1
        
    END
1
5 / 5 / 4
Регистрация: 24.03.2010
Сообщений: 241
Записей в блоге: 1
21.01.2018, 13:57  [ТС] 3
Цитата Сообщение от IamRain Посмотреть сообщение
/ *во внешнем цикле */
..
Не совсем понял, что тут имеете ввиду?

Выходит, что приведенный Вами код - это код для внутреннего цикла ?

Добавлено через 6 минут
Цитата Сообщение от RCF Посмотреть сообщение
Не совсем понял, что тут имеете ввиду?

IamRain,

я, разобрался. Спасибо за наводку!
0
3462 / 2473 / 695
Регистрация: 02.08.2011
Сообщений: 6,704
21.01.2018, 13:57 4
Вот полный код.
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
declare @lv_max_t001w integer
declare @lv_min_t001w integer
declare @lv_t001w NVARCHAR(4)
 
declare @lv_pfach nvarchar(1)
 
declare @lv_max_rec bigint
declare @lv_min_rec integer
 
DECLARE @lt_marc TABLE (id int identity, MATNR nvarchar(18), WERKS nvarchar(4));
 
SELECT  @lv_max_t001w = max(IDT001W) FROM T001W -- определяем кол-во записей в табл T001W
set  @lv_min_t001w = 1
 
set @lv_max_rec = 10 -- необходимое кол-во озм, которые должны быть растиражированы на каждую запись в T001W
set @lv_min_rec = 1 -- начальное для цикла значение
DECLARE @ly_maxCurrent INTEGER; 
DECLARE @ly_minCurrent INTEGER; 
 
WHILE  @lv_min_rec <= @lv_max_rec 
    BEGIN
    SET NOCOUNT ON
       
    SET @ly_maxCurrent = @lv_max_t001w;
   SET @ly_minCurrent = @lv_min_t001w;
 
 
    WHILE @ly_minCurrent <= @ly_maxCurrent
 
                BEGIN
                    SELECT @lv_t001w = werks, @lv_pfach = pfach FROM t001w where idt001w = @lv_min_t001w
 
                    ----if  @lv_pfach = '' -- если испрользуется, то вставляем
                    ----    begin
                            INSERT INTO @lt_marc (MATNR, WERKS) VALUES (@lv_min_rec, @lv_t001w)
                    ------end
 
                    set @lv_min_t001w = @lv_min_t001w + 1
                END
 
            set @ly_minCurrent = @ly_minCurrent+ 1
        
    END
 
    select * from @lt_marc
После первой итерации по внешнему циклу @lv_min_t001w уже был больше @lv_max_t001w по всем остальным итерациям. То есть у вас выполняется всего лишь одна итерация внешнего цикла.
Значения надо просто сбрасывать. Добавлены доп.переменные через которые и рассчитывается условия для внутреннего цикла.
0
1116 / 761 / 183
Регистрация: 27.11.2009
Сообщений: 2,269
21.01.2018, 14:40 5
Непонятно, зачем здесь вообще какие-то циклы?
Один INSERT, - и всё
0
3462 / 2473 / 695
Регистрация: 02.08.2011
Сообщений: 6,704
21.01.2018, 14:43 6
iap, ТС, видимо, пока еще не привык к декларативному программированию.
Все же иногда, имхо, без императивщины не обойтись. Например, когда нужно собрать из коллекции скаляр (я про cursor).
0
5 / 5 / 4
Регистрация: 24.03.2010
Сообщений: 241
Записей в блоге: 1
21.01.2018, 17:27  [ТС] 7
Цитата Сообщение от IamRain Посмотреть сообщение
Значения надо просто сбрасывать.
Да, разобрался. Спасибо!

Изначально про это почему-то не подумал.
0
3462 / 2473 / 695
Регистрация: 02.08.2011
Сообщений: 6,704
21.01.2018, 17:28 8
Цитата Сообщение от RCF Посмотреть сообщение
Изначально про это почему-то не подумал.
Синтаксис TSQL затуманил разум.
0
5 / 5 / 4
Регистрация: 24.03.2010
Сообщений: 241
Записей в блоге: 1
21.01.2018, 18:26  [ТС] 9
Цитата Сообщение от iap Посмотреть сообщение
Один INSERT, - и всё
Как?
0
1116 / 761 / 183
Регистрация: 27.11.2009
Сообщений: 2,269
21.01.2018, 18:37 10
T-SQL
1
INSERT ... SELECT ... FROM ... WHERE ...
Правильное условие WHERE - и дело в шляпе.
0
3499 / 2083 / 742
Регистрация: 02.06.2013
Сообщений: 5,078
21.01.2018, 20:05 11
Цитата Сообщение от RCF Посмотреть сообщение
Как?
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
declare @c int = 10;
 
with n as
(
 select 1 as n
 union all
 select n + 1 from n where n < @c
)
insert into @lt_marc
 (MATNR, WERKS)
 select
  n.n, t.werks
 from
  t001w t cross join
  n;
0
5 / 5 / 4
Регистрация: 24.03.2010
Сообщений: 241
Записей в блоге: 1
26.01.2018, 11:16  [ТС] 12
Цитата Сообщение от invm Посмотреть сообщение
declare @c int = 10;
Спасибо за решение!

Но при @c => 102 - ошибка:

T-SQL
1
2
Сообщение 530, уровень 16, состояние 1, строка 3
Выполнение инструкции прервано. Максимальная рекурсия 100 была использована до завершения инструкции.
0
1643 / 1144 / 171
Регистрация: 23.07.2010
Сообщений: 6,794
26.01.2018, 11:20 13
OPTION (MAXRECURSION n)
0
26.01.2018, 11:20
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.01.2018, 11:20
Помогаю со студенческими работами здесь

Цикл if внутри цикла for
Добрый день всем сюда зашедшим, пишу код на Pascal для программы isis/base возник вопрос, вот этот...

Цикл внутри цикла
Возможно ли сделать ветвлением? Здесь же не одно истинное значение, как и ложное

Цикл внутри условия цикла
Можно ли внутрь условия засунуть цикл как показано ниже.Если да то что тут не так подскжите. Гугл...

Можно ли располагать цикл внутри цикла?
Здравствуйте. Можно ли располагать цикл внутри цикла? for(....) { if() { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru