Выполнение цикла WHILE занимает больше времени и зависает Managment studio

#sql-server #tsql

#sql-сервер #tsql

Вопрос:

Я хочу выполнить 3 хранимые процедуры в WHILE цикле. Итак, сначала я ищу данные, которые мне нужны как:

 DECLARE @FBOMDesigns AS TABLE
(
      DesignKey INT,
      ParentDesignKey INT,
      ProjectKey INT,
      CurrentRow INT
)

INSERT INTO @FBOMDesigns
    SELECT 
        D.DesignKey, [D].ParentDesignKey,
        [PD].[ProjectKey],
        ROW_NUMBER() OVER(ORDER BY D.[DesignKey]) AS [CurrentRow]
    FROM 
        ##Design AS D  
    INNER JOIN 
        ##ProjectDesign AS PD ON D.DesignKey = PD.DesignKey
    WHERE  
        DesignTypeGuid = '13B58AC4-F8BD-431F-8977-BE9C1FF25C7C'

DECLARE @NewCDDesigns AS TABLE 
(
     DesignKey INT,
     CurrentRow INT
)

INSERT INTO @NewCDDesigns
    SELECT 
        D.DesignKey,
        ROW_NUMBER() OVER (ORDER BY D.DesignKey) AS CurrentRow
    FROM 
        ##Design AS D
    INNER JOIN 
        ##ProjectDesign AS PD ON D.DesignKey = PD.DesignKey
    INNER JOIN 
        @FBOMDesigns as FD ON PD.ProjectKey = FD.ProjectKey
    WHERE 
        PD.ProjectKey IN (SELECT ProjectKey FROM @FBOMDesigns) 
        AND D.DesignTypeGuid = '54FBBC23-CB9A-4311-9D7F-0DD7A774F33D' 
        AND D.Folio = 0
  

Как вы можете видеть, я создаю две таблицы с информацией

Как только у меня это есть, я устанавливаю переменные while:

 DECLARE @counter   INT = 1,
        @max       INT = 0,
        @DesignKey INT

SET @max = (SELECT COUNT(DesignKey) FROM @NewCDDesigns)
  

Примечание: @max значение равно 628

Таким образом, цикл должен пройти 628 раз:

 WHILE @counter <= @max
BEGIN
    DECLARE @CurrentDesignKey INT = (SELECT TOP 1 DesignKey FROM @NewCDDesigns 
                                     WHERE [CurrentRow] = @counter)
    DECLARE @CurrentPreviousDesignKey INT = (SELECT TOP 1 DesignKey FROM @FBOMDesigns 
                                             WHERE ParentDesignKey =  (SELECT TOP 1 DesignKey FROM @NewCDDesigns WHERE [CurrentRow] = @counter))
    EXEC [copyPreviousDesign]
        @DesignKey = @CurrentDesignKey  ,
        @PreviousDesignKey = @CurrentPreviousDesignKey

    EXEC [copyCustomersFromPreviousDesign]
        @DesignKey =@CurrentDesignKey ,
        @PreviousDesignKey = @CurrentPreviousDesignKey

    EXEC [addDefaultTasksToDesign]
        @DesignKey =  @CurrentDesignKey
END
  

Проблема в том, что запрос занял слишком много времени, SQL Server Management Studio застрял на 29 минуте, и мне нужно принудительно закрыть. Есть ли какой-нибудь способ сделать это быстрее?

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

1. «Есть ли какой-нибудь способ сделать это быстрее?» Да, не используйте WHILE цикл. SQL Server предназначен для операций на основе наборов, а не интерактивных, поэтому он хорошо выполняет первое и плохо — второе. Если вы можете объяснить, какова ваша фактическая цель здесь, мы можем помочь вам превратить то, что у вас есть, в процесс, основанный на наборе.

2. У вас также есть top 1 без order by. Не имеет значения, какую строку вы получите?

Ответ №1:

Вы должны увеличить @counter внутри цикла while. Это бесконечный цикл.

выберите @counter = @counter 1;

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

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