#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, это даст вам четкое представление