AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 17.02.2011, 10:41   #1  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Аксапта ограничивает размер строки-маски в операторе like размером фильтруемого поля
Обнаружил сейчас неприятную особенность оператора like. Заключается она в следующем.

Допустим в таблице есть поле длиной 10 символов. В нём хранится значение занимающее полностью весь столбец, т.е. тоже длиной в 10 символов. Допустим это
"ABC0123456". Если попытаться отфильтровать его по условию like "*ABC0123456", то в результате получим пустую выборку. Потому что, на самом деле маска длиной 11 символов обрезается справа до длины поля, т.е до 10. В результате маска превращается в "*ABC012345".И если в таблице будут записи удовлетворяющие этому обрезанному критерию, то они выберутся. Если в маску добавить две звёздочки, то соответственно справа обрежутся уже два символа.

В начале я подумал, что это Аксаптовские проделки, но поэкспериментировав на SQL сервере обнаружил что проблема глубже.

Скорее всего для внутреннего представления значения маски SQL Server использует тот же самый тип данных, что и у поля, по которому происходит фильтрация.

В случае временных таблиц, работу с которыми аксапта реализует самостоятельно, всё работает корректно.
Старый 17.02.2011, 12:12   #2  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Версия Аксапты, версия сиквела ?
Старый 17.02.2011, 12:41   #3  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
А Вы не записываете маску в переменную? Может, проблема с типом данных той переменной, в которую записали маску?

X++:
str 3 testVar = "1234";
;

print testVar;
pause;
Старый 17.02.2011, 13:07   #4  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
AX2009 SP1
SQL Server 2008 R2
X++:
static void JobTestLike20110217(Args _args)
{
//    TableTestLike.Field1 StringSize 10

    TableTestLike TableTestLike;
    Range mask = '*ABC0123456';
    ;
    
    delete_from TableTestLike;
    
    TableTestLike.clear();
    TableTestLike.Field1 = 'ABC0123456';
    TableTestLike.insert();

    TableTestLike.clear();
    TableTestLike.Field1 = 'ABC012345';
    TableTestLike.insert();
    
    info(strfmt('mask: %1', mask));
    while select TableTestLike
    where
        TableTestLike.Field1 like mask
    {
        info(TableTestLike.Field1);
    }
}
Старый 17.02.2011, 13:30   #5  
TasmanianDevil is offline
TasmanianDevil
Мрачный тип
Аватар для TasmanianDevil
Злыдни
 
885 / 389 (14) ++++++
Регистрация: 24.01.2005
Адрес: Томск
Мда ...
Явно не в переменной дело, да и не в сервере очень даже может быть.
Вариант того, что особо "одаренное" ядро может обрезать строку ограничения до размерности поля в репозитарии, выдавая такого "кастрата" на сервер, рассматривался ? "Кастрат", я так понимаю, обнаружился при трассировке переданного системой запроса ?
__________________
Мы летаем, кружимся, нагоняем ужасы ...

Последний раз редактировалось TasmanianDevil; 17.02.2011 в 13:32.
Старый 17.02.2011, 13:43   #6  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
В том то и дело что результат выполнения такого запроса в SQL Server Management Studio точно такой же. Т.е. ошибка не в аксапте а в СУБД
Старый 17.02.2011, 13:53   #7  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Профайлер SQL-сервера показывает, что на сервер попадает уже обрезанное значение. Т.е. действительно это ошибка ядра Axapta. И действительно искомое значение обрезается до размерности поля в репозитарии

Например, для следующего запроса профайлер SQL-сервера показывает, что в качестве параметра передается только первые 10 символов константы

X++:
    while select TableTestLike
    where
        TableTestLike.Field1 == 'ABC0123456890123456789'
    {
        info(TableTestLike.Field1);
    }
Старый 17.02.2011, 13:55   #8  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Можно обойтись без профайлера SQL, ограничившись штатной трассировкой запросов, если в запросе использовать hint forceliterals. Хотя в запросе с литералами и без них может получиться разное значение маски
Старый 17.02.2011, 13:57   #9  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
В том то и дело что результат выполнения такого запроса в SQL Server Management Studio точно такой же. Т.е. ошибка не в аксапте а в СУБД
Нет. Вот как раз в Management Studio все в порядке. Запрос вида

Код:
select * from TableTestLike
where TableTestLike.Field1 like '%ABC0123456'
Вернет то, что и должен вернуть. Именно запись с 6 на конце.

Microsoft SQL Server 2005 - 9.00.4285.00 (Intel IA-64) Feb 8 2010 23:35:42
Copyright (c) 1988-2005 Microsoft Corporation
Standard Edition (64-bit) on Windows NT 5.2 (Build 3790: Service Pack 2)

----------------------

Даже с учетом того, что MS SQL выполняет не прямой запрос, в фетчит курсор, все-равно все в порядке

Код:
DECLARE @Field1 varchar(10)

DECLARE cursor1 CURSOR FOR
SELECT Field1 
FROM TableTestLike
where Field1 like '%ABC0123456'

OPEN cursor1
FETCH NEXT FROM cursor1 into @Field1 
WHILE @@FETCH_STATUS = 0
   BEGIN
	select 'cursor1', @Field1 
      FETCH NEXT FROM cursor1 into @Field1 ;
   END;
CLOSE cursor1
DEALLOCATE cursor1

Последний раз редактировалось Владимир Максимов; 17.02.2011 в 14:02.
За это сообщение автора поблагодарили: S.Kuskov (2).
Старый 17.02.2011, 14:05   #10  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Что же делать ?
QueryRun нас спасет ?
Старый 17.02.2011, 14:10   #11  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Да на SQL Server я зря наговаривал (видимо я в попыхах перепутал процент со звёздочкой), там всё в порядке, чего не скажешь про аксапту

Цитата:
Сообщение от Logger Посмотреть сообщение
Что же делать ?
QueryRun нас спасет ?
Неа
X++:
static void JobTestLike20110217(Args _args)
{
//    TableTestLike.Field1 StringSize 10
    Query Query;
    QueryRun QueryRun;


    TableTestLike TableTestLike;
    Range mask = '*ABC0123456';
    ;

    delete_from TableTestLike;

    TableTestLike.clear();
    TableTestLike.Field1 = 'ABC0123456';
    TableTestLike.insert();

    TableTestLike.clear();
    TableTestLike.Field1 = 'ABC012345';
    TableTestLike.insert();

    info(strfmt('mask: %1', mask));
    while select TableTestLike
    where
        TableTestLike.Field1 like mask
    {
        info(TableTestLike.Field1);
    }

    Query = new Query();
    Query.addDataSource(tablenum(TableTestLike)).addRange(fieldNum(TableTestLike, Field1)).value(mask);
    QueryRun = new QueryRun(Query);
    while(QueryRun.next())
    {
        TableTestLike = QueryRun.get(tablenum(TableTestLike));
        info(TableTestLike.Field1);
    }
}
Старый 17.02.2011, 14:25   #12  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Можно обойтись без профайлера SQL, ограничившись штатной трассировкой запросов, если в запросе использовать hint forceliterals. Хотя в запросе с литералами и без них может получиться разное значение маски
Да, хинт forceliterals спасает положение. Но только если использовать переменные

X++:
  while select forceLiterals TableTestLike
    where
        TableTestLike.Field1 like mask
    {
        info(TableTestLike.Field1);
    }
Если же вместо переменной использовать константу. Т.е. писать запрос так

X++:
  while select forceLiterals TableTestLike
    where
        TableTestLike.Field1 like '*ABC0123456'
    {
        info(TableTestLike.Field1);
    }
То вне зависимости от использования хинта forceliterals или forceplaceholders на сервер уходит запрос вида

Код:
SELECT *
FROM TableTestLike
WHERE (Field1 like '\%ABC0123456' ESCAPE '\' )
Подобный запрос вообще ничего не возвращает. Но здесь проблема в обратном слеше и действительно уже в собственно MS SQL. Очевидно, происходит не корректное исключение этого самого слеша из условия отбора
Старый 17.02.2011, 16:04   #13  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Просьба модераторов изменить заголовок темы
SQL Server Аксапта ограничивает размер строки-маски в операторе like размером фильтруемого поля
Старый 17.02.2011, 16:31   #14  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,273 / 3466 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Просьба модераторов изменить заголовок темы
SQL Server Аксапта ограничивает размер строки-маски в операторе like размером фильтруемого поля
Сделано
__________________
Возможно сделать все. Вопрос времени
Теги
like, баг

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Параметр ком.строки crosscompany и место поля dataareaid в индексах gl00mie DAX: Программирование 6 18.02.2013 13:28
При суммарной обработке закупок аксапта удаляет строки разноски счета и накладной maxkov DAX: Функционал 15 14.12.2012 17:27
размер 1 записи (строки) SHiSHok DAX: Программирование 15 10.08.2009 18:02
Denis Fedotenko: Новые поля в складских проводках Blog bot DAX: База знаний и проекты 10 24.05.2007 11:57
Получить значение поля таблицы по номеру (Id) поля Anais DAX: Программирование 2 15.04.2004 13:00
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 18:40.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.