Удалить текущую строку из внутренней таблицы в цикле

Могу ли я безопасно удалить активную строку при просмотре внутренней таблицы?

В качестве примера рассмотрим этот код:

LOOP AT lt_itab INTO ls_wa.
    IF [...] . " A check that can't be done inside a 'DELETE lt_itab WHERE'
        DELETE lt_itab INDEX sy-tabix
        " OR
        DELETE lt_itab FROM ls_wa.
    ENDIF.
ENDLOOP.

Безопасно ли удалять подобные записи или эта логика будет работать не так, как задумано?

Должен ли я вместо этого сохранить уникальный идентификатор для строк во временном itab и запустить DELETE lt_itab WHERE после цикла?

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


person Lilienthal    schedule 13.05.2014    source источник


Ответы (2)


Безопасно это или нет, во многом зависит от ваших навыков программирования. Он имеет определенный результат, и вам решать, правильно ли использовать команды. Обычно безопасно, если после оператора DELETE внутри цикла ничего не происходит. Вы можете выпустить инструкцию CONTINUE сразу после удаления, чтобы убедиться, что это так.

Не используйте DELETE lt_itab INDEX sy-tabix. Если вы используете в своей проверке какой-либо оператор, который изменяет sy-tabix в качестве побочного эффекта (например, поиск какой-либо записи в проверочной таблице или вызов функционального модуля / метода, который делает это ), вы в конечном итоге удалите неправильные строки.

Имейте в виду, что вы можете просто использовать оператор DELETE lt_itab. в своем примере, поскольку удаляемая строка является текущей.

Если в вашей таблице может быть несколько одинаковых строк, ваш второй вариант DELETE lt_itab FROM ls_wa. удалит их все, а не только текущую - будет ли это предназначено, зависит от ваших требований.


РЕДАКТИРОВАТЬ: повторить «определенный результат»: текущая строка удаляется. Здесь нет «продолжения со следующей строки» - добавив INTO var, вы фактически скопировали всю строку в свою переменную. Эта переменная не будет затронута, она просто не синхронизирована с таблицей. Это могло быть намеренно - система не может этого знать. Если вместо этого вы используете символ поля, это будет UNASSIGNED, что - опять же - может быть тем, что вы намеревались - а потом опять же, возможно, нет.

person vwegert    schedule 13.05.2014
comment
Итак, определенный результат, который вы упомянули, заключается в том, что текущая строка удаляется, а цикл продолжается со следующей строки таблицы без пропуска строк или преждевременного завершения? Другими словами, является ли цикл по внутренней таблице для удаления подмножества ее строк хорошей практикой, когда DELETE ... WHERE не является вариантом, и в цикл не включена никакая другая логика? - person Lilienthal; 13.05.2014
comment
Я добавил еще несколько деталей об определенном результате, но я бы сказал, что да, это обычная и хорошая практика при правильной реализации. - person vwegert; 13.05.2014
comment
Здравствуйте, просто вопрос-замечание - ваш ответ также действителен, если я удалю не текущую строку, а несколько следующих произвольных строк? Например. ЦИКЛ НА itab НАЗНАЧЕНИЕ ‹wa› WHERE cond = X. УДАЛИТЬ itab WHERE id ‹wa› -id = id AND cond ‹› X. ENDLOOP. Спасибо! - person 87element; 01.12.2015
comment
@ 87element В основном да. Итог: если вы измените набор данных, который в настоящее время просматриваете, вам лучше убедиться, что вы знаете, что делаете. - person vwegert; 01.12.2015

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

GET CURSOR LINE SY-CUROW .
DELETE ST_MAT INDEX SY-CUROW.
person Silent Core    schedule 16.04.2018
comment
Как правило, совет использовать GET CURSOR LINE без какой-либо информации об обработке списка (которую OP не предоставил), по крайней мере, вводит в заблуждение и, очень вероятно, просто неправильно. - person vwegert; 24.05.2018