Цикл WHILE для нескольких запусков ХП

SilentSageMan
Дата: 03.02.2009 14:44:48
ДД.
автор
DECLARE @P_Var varchar(200), @SQL NVARCHAR(MAX), @IX_max int, @IX_var int
DECLARE @Table_Var TABLE (
[IX] [int] IDENTITY(1,1) NOT NULL,
[P_Var] [int] NOT NULL)

SET @P_Var='12, 13, 14, 15, 16, 17'--количество и качество чисел внутри @P_Var изменяется

SET @SQL = 'SELECT ' + REPLACE(@P_Var,',',' UNION ALL SELECT')
INSERT INTO @Table_Var
EXEC(@SQL)
--теперь в @Table_Var при каждом исполнении данного запроса количесвто строк будет равно
--количеству чисел внутри @P_Var, а по столбцу P_Var соответственно каждой строке свое число
SET @IX_max = (SELECT MAX(IX) FROM @Table_Var)
SET @IX_var=1
WHILE @IX_var<=@IX_max
BEGIN
SET @VAR = (SELECT P_Var FROM @Table_Var WHERE @IX_var=IX)
--===========================================
EXECUTE [DB].[dbo].[MySP]
@VAR
--некая ХП которую необходимо исполнять последовательно по каждому числу в @P_Var
--то есть сначала [dbo].[MySP] должна исполнится для 12, потом для 13, и т.д., будет у нее и выходные
--параметры, которые будут свидетельствовать об окончании выполнения ХП.
--ХП не написана пока, только архитектура, но первое что нужно сделать это инфраструктуру такого вот вызова
--этой ХП. Думал про курсоры, но вроде они - это еще менее оптимальный вариант.
--При каждом вызове этого запроса @P_Var может содержать только от 1-го до 23 элементов!

--===========================================
SET @IX_var=@IX_var+1
END

Кто бы как сделал по другому?
Matroz
Дата: 03.02.2009 15:41:33
прочитал по диагонали, если правильно понял, основная проблема - передать массив чисел в ХП.
Если так, то как вариант, создать перед запуском ХП временную таблицу #numbers (не табличную переменную) и сложить в нее числа. Она будет видима внутри процедуры
Паганель
Дата: 03.02.2009 15:49:11
автор
сначала [dbo].[MySP] должна исполнится для 12, потом для 13, и т.д.
А если в каком-либо другом порядке - нормально будет,
или для Вашей задачи это недопустимо?
SilentSageMan
Дата: 03.02.2009 16:02:19
Matroz
основная проблема - передать массив чисел в ХП
...не совсем, мне надо последовательно выполнять процедуру с разными входными переменными. Причем если переменных пять, то и ХП нужно выполнить 5 разу, по разу с каждой переменной. Порядок значения не имеет.
Паганель
Дата: 03.02.2009 16:04:15
SilentSageMan
Дата: 03.02.2009 16:41:36
Паганель
Массивы и Списки в SQL Server
Выбирайте

Выбрал...5.1. Список integer элементов...отнес архитектору, он вроде потестил на 23-х элементах, сказал, что пока останавливаемся на моем варианте, так как по ходу тоже самое, а кода в целом меньше :)
Glory
Дата: 03.02.2009 16:46:13
SilentSageMan
Паганель
Массивы и Списки в SQL Server
Выбирайте

Выбрал...5.1. Список integer элементов...отнес архитектору, он вроде потестил на 23-х элементах,

Это очень презентативный тест для замера производительности
Slider_spb
Дата: 03.02.2009 18:39:19
на основе данной статьи сделал следующую функцию:
CTREATE FUNCTION dbo.fnSplitToINT(@tstr varchar(8000), @Delimiter char(1) = ',')
RETURNS @List TABLE (listpos int NOT NULL, ListVal int NOT NULL)
AS
BEGIN
DECLARE @pos      int,
        @textpos  int,
        @chunklen smallint,
        @str      varchar(8000),
        @tmpstr   varchar(8000),
        @leftover varchar(8000),
        @sCount   int

  SET @sCount = 0
  SET @textpos = 1
  SET @leftover = ''
  WHILE @textpos <= datalength(@tstr) / 2
  BEGIN
    SET @chunklen = 4000 - datalength(@leftover) / 2
    SET @tmpstr = ltrim(@leftover + substring(@tstr, @textpos, @chunklen))
    SET @textpos = @textpos + @chunklen

    SET @pos = charindex(@Delimiter, @tmpstr)
    WHILE @pos > 0
    BEGIN
      SET @sCount = @sCount + 1
      SET @str = substring(@tmpstr, 1, @pos - 1)
      INSERT @List(listpos, ListVal) VALUES(@sCount, convert(int, @str))
      SET @tmpstr = ltrim(substring(@tmpstr, @pos + 1, len(@tmpstr)))
      SET @pos = charindex(@Delimiter, @tmpstr)
    END
    SET @leftover = @tmpstr
  END
  IF ltrim(rtrim(@leftover)) <> ''
    INSERT @List(listpos, ListVal) VALUES(@sCount + 1, convert(int,@leftover))
RETURN
END
Аналогично для GUID и String.
Пример использования:
CREATE PROCEDURE dbo.spTestSave
  @RID uniqueidentifier,
  @UIDS_OUTPUT varchar(8000),
  @UIDS_INPUT varchar(8000),
  @LINKS_TYPE varchar(8000)
AS
INSERT INTO WF_LINKS(RID,UID_OUTPUT,UID_INPUT,LINK_TYPE)
SELECT @RID, v1.ListVal, v2.ListVal, v3.ListVal FROM dbo.fnSplitToGUID(@UIDS_OUTPUT, DEFAULT) v1
INNER JOIN dbo.fnSplitToGUID(@UIDS_INPUT, DEFAULT) v2 ON v1.listpos = v2.listpos
INNER JOIN dbo.fnSplitToINT(@LINKS_TYPE, DEFAULT) v3 ON v1.listpos = v3.listpos
SilentSageMan
Дата: 03.02.2009 19:55:07
SilentSageMan
Паганель
Массивы и Списки в SQL Server
Выбирайте

Выбрал...5.1. Список integer элементов...отнес архитектору, он вроде потестил на 23-х элементах, сказал, что пока останавливаемся на моем варианте, так как по ходу тоже самое, а кода в целом меньше :)

Для данной ХП, вх переменная которой м.б. только от 1 до 23, тест очень даже то что надо - это раз, а два концепция при прочих равных одна и та же, я имею ввиду перебор через WHILE. Я рассчитывал, на более радикальный вариант - например с использованием курсора...
Не забываем, курс будет перебирать максимум 23 строки ;)
LSV
Дата: 04.02.2009 12:42:50
Я обычно делаю временную таблицу (например SELECT ... INTO если запрос быстрый) и перебираю ее курсором с дальнейшим вызовом ХП с нужными параметрами.
Не думаю, что другие способы будут более рациональны. При правильном подходе курсоры полезная вещь.