Показать сообщение отдельно
Старый 14.04.2009, 14:47   #1  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,996 / 3293 (117) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
ORA-01480 в фильтрах
Описание проблемы :
Ax3.0 KR3
База ORACLE

Если фильтруем таблицу по полю, например так :
X++:
static void Job492(Args _args)
{   // пример сделан для стандартной длины поля LedgerJournalTable.JournalNum - 10 символов
    // выравнивание роли не играет
    LedgerJournalTable      LedgerJournalTable;
    ;
    select
    LedgerJournalTable
    where
        LedgerJournalTable.JournalNum like "012_456789" + "*" // будет ошибка ORA-01480
//        LedgerJournalTable.JournalNum like "012_45678" + "*"  // будет ошибка ORA-01480
//        LedgerJournalTable.JournalNum like "012_4567" + "*" // все нормально
//        LedgerJournalTable.JournalNum like "012_4567" + "**" // будет ошибка ORA-01480
//        LedgerJournalTable.JournalNum like "*" + "012_4567" + "*" // будет ошибка ORA-01480
//        LedgerJournalTable.JournalNum like "0123456789" + "*" // все нормально
//        LedgerJournalTable.JournalNum like "012345678" + "*" // все нормально
    ;
    info("Ок");
}
То БД выдает ошибку ORA-01480
Ошибка происходит когда выполнено 4 условия
1. Используется like (не важно статический запрос или range с * в Query)
2. В фильтре использован символ _
3. Длина строки + число символов "_" в строке больше длины поля в БД (11 и 12 символов для нашего примера)
4. Запрос на БД идет с параметрами. (т.е. использованы placeholders)

Судя по всему аксапта при формировании запроса к БД посредство интерфейса OCI использует строки оканчивающиеся нулем.
http://www.sey.ru/~basile/ociProgGuide/oci03typ.htm
Цитата:
....
STRING

The null-terminated STRING format behaves like the VARCHAR2 format (datatype code 1), except that the string must contain a null terminator character. This datatype is most useful for C language programs.
Input

The string length supplied in the OCIBindByName() or OCIBindByPos() call limits the scan for the null terminator. If the null terminator is not found within the length specified, Oracle issues the error

ORA-01480: trailing null missing from STR bind value
....
и в ряде случаев некорректно сообщает длину строки, что приводит к тому что символ окончания строки не найден.

Символ "_" является служебным для БД и поэтому чтобы корректно выполнить запрос с условие like на оракл уходит в качестве параметр значение '012\_45678%' а не 012_45678% т.е. длина строки параметра неожиданно увеличивается, и становится больше заявленной, что приводит к ошибке ORA-01480.

Кто как обходит такие глюки ?
Неприятно то что может вылезти на безобидных запросах - например пользователь ищет нужный ему журнал (а автоматически настраиваемые номерные серии часто содержат символ "_" )

Можно везде навтыкать литералов для обхода указанного глюка, но хочется более изящное решение.

Последний раз редактировалось Logger; 14.04.2009 в 15:28. Причина: Уточнение
За это сообщение автора поблагодарили: dn (1).