Цикл SQL while не обновляет таблицу

#sql #sql-server #tsql

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

Вопрос:

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

 DECLARE 
    @IdProcesso  VARCHAR(20)
    IF(NOT OBJECT_ID('tempdb..#PROCESSOS_PENDENTE') IS NULL)        
BEGIN        
    DROP TABLE #PROCESSOS_PENDENTE;        
END   
SELECT IdProcesso as IdProcesso
INTO #PROCESSOS_PENDENTE
FROM fornecedores.aceite WHERE FlgEmProcesso = 0

--PERCORRE TODOS OS REGISTROS E ENVIA OS EMAILS
WHILE (exists (select IdProcesso from #PROCESSOS_PENDENTE))  
BEGIN       
 UPDATE fornecedores.aceite set FlgEmProcesso = 1
     WHERE IdProcesso = @IdProcesso

 END
  

Это процедура, которую я использую, теперь она работает с изменениями, которые были предложены.

 ALTER procedure [Fornecedores].[prConsultaStatusProcesso]
as

DECLARE 
    @IdProcesso  VARCHAR(20),
    @Tag         SYSNAME,
    @IdDoc       UNIQUEIDENTIFIER,
    @Parans      VARCHAR(500)


--TEMP TABLES
IF(NOT OBJECT_ID('tempdb..#PROCESSOS_PENDENTE') IS NULL)        
BEGIN        
    DROP TABLE #PROCESSOS_PENDENTE;        
END   


--ARMAZENA TODOS OS PROCESSOS PENDENTES
SELECT 
    IdProcesso as IdProcesso,
    ROW_NUMBER() OVER(Order by IdProcesso) AS RowNo
INTO #PROCESSOS_PENDENTE
FROM fornecedores.aceite WHERE FlgEmProcesso = 0

--PERCORRE TODOS OS REGISTROS E ENVIA OS EMAILS
DECLARE @Index INT=1,@TotalCount INT=0
SELECT @TotalCount=COUNT(*) FROM #PROCESSOS_PENDENTE

WHILE @Index<=@TotalCount 

    BEGIN       
    SET @IdProcesso=''
    SELECT @IdProcesso=IdProcesso FROM #PROCESSOS_PENDENTE WHERE RowNo=@Index

    SET @Parans = '<Zfif0004Processo><IEmail></IEmail><IIdProcesso>'   @IdProcesso   '</IIdProcesso></Zfif0004Processo>';

    --CONSULTA NO SAP SE O PROCESSO FOI CONCLUIDO COM SUCESSO
    --O RETORNO CHAMARA A PROCEDURE 
    --QUE FICARA RESPONSAVEL EM ENVIAR O EMAIL PARA O FORNECEDOR
    EXEC Geral.prAddMsgOnKolQueue
               @SourceAppName ='TEXT'
              ,@TargetAppName ='TEXT'
              ,@TopicName ='TEXT'
              ,@Tag = 'TEXT'
              ,@TextData = @Parans;

     --ALTERAR O STATAUS DO PROCESSO PARA "EM PROCESSO"
     UPDATE fornecedores.aceite set FlgEmProcesso = 1
        WHERE IdProcesso = @IdProcesso  

    SET @Index=@Index 1

    --EXCLUI REGISTRO DA TABELA TEMPORARIA
    --DELETE #PROCESSOS_PENDENTE Where IdProcesso = @IdProcesso 

END
  

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

1. Для этого вам не нужен цикл. Достаточно одного оператора update

2. Но для этого нужно выполнить поиск по множеству строк в таблице и обновить все, которые имеют статус 0 в FlgEmProcesso.

3. @ViniciusCano да, но это то, что механизм db делает для вас, если вы правильно используете SQL.

4. Обязательно начните думать об операциях на основе наборов в SQL, это сэкономит вам много времени и головной боли в будущем. Оставьте большую часть цикла для py, C #, java и т. Д….

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

Ответ №1:

Перестаньте думать процедурно, вместо этого думайте на основе наборов при работе с SQL.

То, что вы делаете, похоже,

  • выберите все идентификаторы из строк с Processed = 0 во временную таблицу
  • обновите все строки, которые были выбраны во временной таблице, на обработанные = 1

Вы можете добиться этого без цикла while следующим образом:

 SELECT 
    IdProcesso as IdProcesso,
    ROW_NUMBER() OVER(Order by IdProcesso) AS RowNo
INTO #PROCESSOS_PENDENTE
FROM fornecedores.aceite WHERE FlgEmProcesso = 0

UPDATE fornecedores.aceite set FlgEmProcesso = 1
FROM fornecedores.aceite
JOIN #PROCESSOS_PENDENTE on #PROCESSOS_PENDENTE.IdProcesso = fornecedores.aceite.IdProcesso
  

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

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

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

Ответ №2:

Попробуйте это:

 DECLARE 
    @IdProcesso  VARCHAR(20)
    IF(NOT OBJECT_ID('tempdb..#PROCESSOS_PENDENTE') IS NULL)        
BEGIN        
    DROP TABLE #PROCESSOS_PENDENTE;        
END 

SELECT 
    IdProcesso as IdProcesso,
    ROW_NUMBER() OVER(Order by IdProcesso) AS RowNo
INTO #PROCESSOS_PENDENTE
FROM fornecedores.aceite WHERE FlgEmProcesso = 0

--PERCORRE TODOS OS REGISTROS E ENVIA OS EMAILS
DECLARE @Index INT=1,@TotalCount INT=0
SELECT @TotalCount=COUNT(*) FROM #PROCESSOS_PENDENTE

WHILE @Index<=@TotalCount 
BEGIN       
    SET @IdProcesso=''
    SELECT @IdProcesso=IdProcesso FROM #PROCESSOS_PENDENTE WHERE RowNo=@Index

    UPDATE fornecedores.aceite set FlgEmProcesso = 1
        WHERE IdProcesso = @IdProcesso  

    SET @Index=@Index 1
 END
  

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

1. Я получил эту ошибку. Сообщение 248, уровень 16, состояние 1, строка 21 Преобразование значения varchar ‘0319290916100342’ привело к переполнению столбца int.

2. я обновил его, сначала я думаю, что это INT, но позже понимаю, что это varchar

3. Это сработало, но я мало что понял в этой строке ROW_NUMBER() ВМЕСТО (порядок по IdProcesso) КАК RowNo . Он получает номер строки, но я не понял клаузулу.

4. Он присвоит вашим данным инкрементный номер строки в соответствии с заданным порядком по столбцам, попробуйте понять, используя «SELECT * FROM #PROCESSOS_PENDENTE» перед циклом while, это даст вам четкое представление