Получить значение в зависимости от текущей итерации в цикле while

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

В настоящее время я использую SQL Server Management Studio v18, и я хочу выполнить итерацию с Table Type использованием цикла while, поэтому я делаю:

 CREATE TYPE [VarcharIdTableType] AS TABLE
(
    [FileName] VARCHAR(MAX)
)
 

Затем я использую цикл while как:

 DECLARE @FileTableType [VarcharIdTableType]

INSERT INTO @FileTableType 
VALUES ('test1'),('test2'),('test3')

DECLARE @FileCount INT = (SELECT COUNT(*) FROM @FileTableType), @RowCount INT = 0

WHILE @RowCount <= @FileCount
BEGIN                  
    DECLARE @Content VARCHAR(555)= CONCAT('File name ', @filename)

    SET @RowCount = @RowCount   1;
END
               
 

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

Комментарии:

1. @DaleK Ооо, в моей @Content переменной внутри моего цикла while я использую @filename , но это то, что я хочу, чем переменная @filename не существует, поэтому я хочу получить имя файла dpending каждой итерации

Ответ №1:

ВАЖНО: вам действительно нужен цикл? Поскольку вы не показали нам, каков ваш желаемый конечный результат, мы не можем комментировать. Но во многих случаях подход, основанный на наборе, выполнит то, что вам нужно, и если это так, его следует использовать.

Сделав несколько предположений, таких как отсутствие столбца ID в вашей таблице и возможность удаления строк из вашей табличной переменной, я бы сделал следующее, используя exists, а не подсчитывая строки.

 DECLARE @FileTableType TABLE ([Name] VARCHAR(MAX));

INSERT INTO @FileTableType([Name]) VALUES ('test1'), ('test2'), ('test3');

DECLARE @Content VARCHAR(MAX) = '', @Filename VARCHAR(MAX);

WHILE EXISTS (SELECT 1 FROM @FileTableType)
BEGIN
    SELECT TOP 1 @Filename = [Name] FROM @FileTableType;

    SET @Content = CONCAT('File number ', @Filename);

    DELETE FROM @FileTableType WHERE [Name] = @Filename;
END;
 

Однако было бы лучше иметь известный уникальный идентификатор для значений в табличной переменной, потому что, если у вас есть повторяющиеся имена файлов, в первом коде будут проблемы.

 DECLARE @FileTableType TABLE (id INT IDENTITY(1,1), [Name] VARCHAR(MAX));

INSERT INTO @FileTableType([Name]) VALUES ('test1'), ('test2'), ('test3');

DECLARE @Content VARCHAR(MAX) = '', @Filename VARCHAR(555), @FileId INT;

WHILE EXISTS (SELECT 1 FROM @FileTableType)
BEGIN
    SELECT TOP 1 @FileId = id, @Filename = [Name] FROM @FileTableType;

    SET @Content = CONCAT('File number ', @Filename);

    DELETE FROM @FileTableType WHERE id = @FileId;
END;
 

Обратите внимание на рекомендации:

  • Завершение всех операторов точкой с запятой
  • Перечисление всех столбцов при вставке
  • Используя VARCHAR(MAX) for @Content , поскольку имя файла равно.

Комментарии:

1. Если вам действительно-действительно-действительно нужно перебирать таблицу по строкам, то простой курсор прост и обычно наиболее эффективен: думая, что цикл WHILE не является КУРСОРОМ , какое влияние могут оказать различные параметры курсора? Проклятие параметров курсора

2. @VladimirBaranov это действительно хорошая информация, не стесняйтесь оставлять свой собственный ответ, я просто добавлял недостающую ссылку в код OPs, но ваши предложения улучшают его в дальнейшем.