05.12.2008, 17:48 | #1 |
MCITP
|
Изменение "курсора" в цикле
Всем привет.
Вероятно, конечно, баян, но я не нашёл... Интуитивно так обычно не делал, но вот недавно наткнулся - решил поделиться. Если внутри цикла while select (ну и не только наверное) изменить ссылку табличной переменной используемого курсора на что-то другое, то можно "отгрести" забавные результаты. Проще продемонстрировать, чем объяснить. Пример Jobа (Номер журнала задайте сами): X++: static void ZVV_TestCursorJob(Args _args) { InventTrans inventTrans; InventJournalId _InventJournalId = "СЖ008968"; ; while select inventTrans where inventtrans.TransType == InventTransType::InventTransfer && inventTrans.TransRefId == _InventJournalId { info(strFmt("%1 %2 %3", inventTrans.InventTransId, inventTrans.ItemId, inventTrans.Qty)); } info(strrep('-',30)); while select inventTrans where inventtrans.TransType == InventTransType::InventTransfer && inventTrans.TransRefId == _InventJournalId { info(strFmt("%1 %2 %3", inventTrans.InventTransId, inventTrans.ItemId, inventTrans.Qty)); inventTrans = inventTrans::findRecId(inventTrans.RecId); } } Код: Сообщение (16:45:39) Л_11776612 25472/001 -10,00 Л_11776612 25472/001 10,00 Л_11776613 25472/001 -10,00 Л_11776613 25472/001 10,00 Л_11776614 25472/001 -20,00 Л_11776614 25472/001 20,00 ------------------------------ Л_11776612 25472/001 -10,00 Л_11776612 25472/001 -10,00 Л_11776612 25472/001 -10,00 Л_11776612 25472/001 -10,00 Л_11776612 25472/001 -10,00 Л_11776612 25472/001 -10,00 3.0
__________________
Zhirenkov Vitaly |
|
05.12.2008, 17:58 | #2 |
MCITP
|
Особенно актуально это, наверное, с частоиспользуемыми конструкциями InventDim::findOrCreate()...
__________________
Zhirenkov Vitaly |
|
05.12.2008, 19:52 | #3 |
Участник
|
ну изначально цикл содержит 7 итераций, тоесть 7 записей найдено и эти 7 записей в переменной "inventTrans", а строчка "inventTrans = inventTrans::findRecId(inventTrans.RecId);" находит одну единственную запись ... поидее цикл должен был остановиться после первой записи... но он выполняется 7 раз и пытается сдвинуть курсор, но inventTrans после первой итерации содержит 1 запись
X++: select inventTrans where inventtrans.TransType == InventTransType::InventTransfer && inventTrans.TransRefId == while(inventTrans) { info(strFmt("%1 %2 %3", inventTrans.InventTransId, inventTrans.ItemId, inventTrans.Qty)); inventTrans = inventTrans::findRecId(inventTrans.RecId); next inventTrans; } Последний раз редактировалось DAX; 05.12.2008 в 19:54. |
|
05.12.2008, 20:53 | #4 |
MCITP
|
Так да, будет только одна запись выбираться.
Но это то и понятно... Речь не о том, как это обойти, можно вообще-то и переменную другую завести. Просто может кто не в курсе, чтоб не наступали на грабли.
__________________
Zhirenkov Vitaly |
|
08.12.2008, 10:31 | #5 |
NavAx
|
только мне этот "баг" кажется очевидным?
__________________
И все они создания природы... |
|
09.12.2008, 04:52 | #6 |
Участник
|
|
|
09.12.2008, 11:04 | #7 |
Боец
|
Я вообще прикола не понял... Вы меняете значение курсорв, на основе которой система строит цикл. Зачем его трогать, и зачем потом ломать голову "почему происходит так, а не по-моему"? если угодно, можно создать дополнительную табл. переменную и пользовать её...
|
|
|
За это сообщение автора поблагодарили: Lemming (1). |
09.12.2008, 11:07 | #8 |
Участник
|
А почему он должен выполняться один раз или зацикливаться? Я так понимаю, WHILE SELECT работает следующим образом - сам SELECT выполняется один единственный раз , а потом с помощью WHILE осуществляется навигация по выбранным записям этого SELECT'a (при этом сама выборка в цикле уже не перестраивается)
|
|
09.12.2008, 15:11 | #9 |
MCITP
|
Вот уж не думал, что такая дискуссия разгорится.
На самом деле Аксапта то может и более-менее логично себя ведёт, если подумать. Я её за это и не упрекаю и багом происходящее не называл. Я хотел сказать, что если об этом не знаешь или не думаешь, то "Найти такой баг в коде наверное не всегда может быть просто и очевидно..". Имелось ввиду баг в своём коде.
__________________
Zhirenkov Vitaly |
|
|
|