Имя: Пароль:
1C
1С v8
v8: Ошибка функции ЕСТЬNULL () в 8.2
0 vvp117
 
20.03.12
13:33
Конфигурация: Зарплата и управление персоналом 8.2
Версия конфигурации: 2.5.47.1
Платформа: 8.2.14.519
Суть ошибки: функция ЕСТЬNULL() игнорирует значение с типом NULL в первом параметрею

Вообще ошибка вот в таком коде:

ВЫБРАТЬ ПЕРВЫЕ 100
   ЕСТЬNULL(&Префикс + РО.ОбособленноеПодразделениеЗавершения.Код,"не указано") КАК П10
ИЗ
   РегистрСведений.РаботникиОрганизаций КАК РО
   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК ОРГ
       ПО ОРГ.Ссылка = РО.ОбособленноеПодразделениеЗавершения

Но проще ее увидеть в пустой конфигурации (я использовал основной режим конфигурации [Обычное приложение]).
Создаем пустую конфигурацию с объектами:
1. Справочник [Сотрудники].
2. Справочник [Организации] (тип кода, что ВАЖНО, - Строка).
3. Независимый непериодический регистр сведений [Документы] с измерением [Сотрудник] (тип: СправочникСсылка.Сотрудники) и ресурсом [Организация] (тип: СправочникСсылка.Организации).

Запускаем режим [Предприятие] и добавляем в регистр одну запись, в которой заполняем поле [Сотрудник], а поле [Организация] оставляем пустым.
Затем открываем консоль запросов/отчетов, кому как нравится, и выполняем следующий запрос:

Запрос 1

ВЫБРАТЬ
   Доки.Организация.Код КАК ЧистыйКодОрганизации,
   (&Префикс + Доки.Организация.Код) КАК ПреобразованиеКNULL,
   ЕСТЬNULL(&Префикс + Доки.Организация.Код,"не указано") КАК КодОрганизации
ИЗ
   РегистрСведений.Документы КАК Доки
   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организация КАК ОРГ
       ПО ОРГ.Ссылка = Доки.Организация

где:
&Префикс = "СЗ" (это требуется для решения задачи)

В результате имеем одну запись, в которой:
ЧистыйКодОрганизации = NULL
ПреобразованиеКNULL  = NULL
КодОрганизации       = NULL

Но если выполнить такой запрос:

Запрос 2

ВЫБРАТЬ
   NULL КАК ЧистыйКодОрганизации,
   (&Префикс + NULL) КАК ПреобразованиеКNULL,
   ЕСТЬNULL(&Префикс + NULL,"не указано") КАК КодОрганизации
ИЗ
   РегистрСведений.Документы КАК Доки
   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организация КАК ОРГ
       ПО ОРГ.Ссылка = Доки.Организация

То имеем запись со значениями полей:
ЧистыйКодОрганизации = NULL
ПреобразованиеКNULL  = NULL
КодОрганизации       = "не указано"
что собственно и требуется!!!

ВОПРОС: в чем отличие работы запросов 1 и 2??? почему они дают различные результаты?
может я чего то не понимаю? конечно, можно воспользоваться оператором ВЫБОР вот так:

ВЫБОР
    КОГДА Доки.Организация.Код ЕСТЬ NULL ТОГДА
         "не указано"
    ИНАЧЕ
         &Префикс + Доки.Организация.Код
    КОНЕЦ КАК КодОрганизации

но это не так красиво, т.к. выбирается много полей такого вида:

ЕСТЬNULL(&Префикс + Доки.Организация.Код,"не указано")
1 le_
 
20.03.12
13:38
ЕСТЬNULL(&Префикс + Доки.Организация.Код, "не указано") - как это это не правильно.

ИМХО, лучше так:
Выбор Когда Доки.Организация.Код есть NULL Тогда
"не указано"
Иначе
&Префикс + Доки.Организация.Код
Конец КАК П10
2 vvp117
 
20.03.12
13:42
ну так то оно так, но почему?
я и сам понимаю, что через оператор ВЫБОР все будет корректно работать, но запрос становится менее читабельным с кучей ветвей, а с ЕСТЬNULL все симпатичнее.
мне интереснее почему запрос 1 и запрос 2 возвращает разные результаты.
3 dmpl
 
20.03.12
13:43
(0) Это не ошибка. Надо пробовать

&Префикс +  ЕСТЬNULL(Доки.Организация.Код,"не указано") КАК КодОрганизации
4 mikecool
 
20.03.12
13:45
(0) а в выборке запись вообще присутствует?
5 mikecool
 
20.03.12
13:45
+4 ибо
выбрать ЕстьNull("Один" + Номер, "Два")
Из Документ.РеализацияТоваровУслуг
Где Номер = "23232323232321"
не вернет ни одной записи
6 vvp117
 
20.03.12
13:46
Запись присутствует.
См. вопрос с места:

Но проще ее увидеть в пустой конфигурации (я использовал основной режим конфигурации [Обычное приложение]).
Создаем пустую конфигурацию с объектами:
1. Справочник [Сотрудники].
2. Справочник [Организации] (тип кода, что ВАЖНО, - Строка).
3. Независимый непериодический регистр сведений [Документы] с измерением [Сотрудник] (тип: СправочникСсылка.Сотрудники) и ресурсом [Организация] (тип: СправочникСсылка.Организации).

Запускаем режим [Предприятие] и добавляем в регистр одну запись, в которой заполняем поле [Сотрудник], а поле [Организация] оставляем пустым.
7 Sammo
 
20.03.12
13:48
План запросов какой?
8 vvp117
 
20.03.12
13:48
(3) префикс не нужно прибавлять к результату, иначе, если Доки.Организация.Код ЕСТЬ NULL, будем иметь на выходе такое: "СЗне указано".
9 vvp117
 
20.03.12
13:49
(7) как, используя консоль запросов, увидеть план запросов?
10 Axel2009
 
20.03.12
13:53
ВЫБРАТЬ СтатьяЗатрат.Код, ЕСТЬNULL(СтатьяЗатрат.Код, "0") КАК Поле1 ИЗ Справочник.Номенклатура ГДЕ Ссылка = &Ссылка
возвращает
"", "0"

1С:Предприятие 8.2 (8.2.15.294)
11 dmpl
 
20.03.12
14:05
(8) Ну так используй ВЫБОР.

Что же касается сути вопроса - это классическая ловушка с неявным приведением типов.
12 rs_trade
 
20.03.12
14:08
ветку не читал, сходу &Префикс + NULL не есть правильно
13 vvp117
 
20.03.12
14:12
(10) интересно, что в 1С:Предприятие 8.1 (8.1.15.14) аналогичный код работает корректно
14 vvp117
 
20.03.12
14:13
(12) почему не правильно? на NULL что не умножай, будет NULL, что не прибавляй - NULL. Это весьма удобно.
(11) можно подробнее про неявное приведение типов?
15 Ненавижу 1С
 
гуру
20.03.12
14:15
1С опять недопоняла NULL, а все придумывает Неопределено
Пусть с NULL научатся работать!
16 Wern
 
20.03.12
14:19
Сложение тут не причем.С чего бы коду быть NULL ты же не из соединения берешь код, вот если бы у тебя было "ОРГ.Код" был бы NULL, а так явно "Неопределено".
17 dmpl
 
20.03.12
14:20
(13) Ну, значит, повезло.

(14) При неявной типизации первый аргумент операции сложения, как правило, определяет тип результата (т.е., если к строке число прибавить - в лучшем случае будет строка в виде конкатенации 2 строк - исходной и преобразованного в строку числа, в худшем - вообще ошибка). Разыменовывание неопределенной ссылки и приведение ее к типу Строка для сложения с строковым префиксом априори дает неопределенный результат. Не факт что NULL.
18 Ненавижу 1С
 
гуру
20.03.12
14:24
(16) не суть важно откуда, это неявное соединение - иди учи матчасть
19 vvp117
 
20.03.12
14:25
(10) Вы правы.
Дело в версии платформы, установил 1С:Предприятие 8.2 (8.2.15.294) и проблема решилась.
Кстати, аналогичный запрос в Microsoft SQL Server Management Studio (10.0.1600.22) также отрабатывает корректно.
(17) Спасибо за разъяснение
Ну в данном случае с 1С просто потребовалось обновиться.
Всем спасибо. Вопрос закрыт.
20 Axel2009
 
20.03.12
14:27
(17) если есть хоть один NULL, то абсолютно монопенисуально какой первый. все становится NULL
21 dmpl
 
20.03.12
14:30
(19) Чтобы потом опять вдруг не перестало работать - лучше избегать сложения разнотипных аргументов. Это относится ко всем языкам программирования, на таких ошибках многие шишки набивают.

(20) А кто сказал, что при неявном преобразовании к типу Строка будет NULL? А вдруг Неопределено? ;)
22 Ненавижу 1С
 
гуру
20.03.12
14:31
(21) больше кидай на вентилятор
23 Axel2009
 
20.03.12
14:32
(21) стандарт SQL сказал
24 dmpl
 
20.03.12
14:35
(23) А запросы вы на языке SQL пишите, да? И давно он запросы на русском языке стандартизировал?
25 Ненавижу 1С
 
гуру
20.03.12
14:38
(24) гнилые отмазы 1с-филов-sql-фобов
26 Axel2009
 
20.03.12
14:39
(24) т.е. вы предполагаете, что 1с анализирует
&Префикс + колонкакакаято
и преобразует в чтото наподобии:
ВЫБОР КОГДА колонкакакаято ЕСТЬ NULL ТОГДА &Префикс ИНАЧЕ &Префикс + колонкакакаято КОНЕЦ
так чтоли?
27 vvp117
 
20.03.12
14:39
(23), (21) как бы намекает, что от 1С можно ожидать внезапного выхода за рамки стандартов SQL. Ведь в 8.1.15.14 этой ошибки нет, в 8.2.14.519 она вдруг появляется, а в 8.2.15.294 ее снова нет! блуждающий баг...
28 Omskdizel
 
20.03.12
14:42
(27) Закрыто только полвопроса. Решение показало то, что вторые полвопроса надо срочно решать, а именно: такие неоднозначные конструкции при правильном подходе приходить в голову не должны, как следствие будете в достаточно большой мере защищены от прихотей реализации 1С.
29 Axel2009
 
20.03.12
14:42
(27) нужен текст запроса SQL, в который преобразуется первоначальный запрос
30 Omskdizel
 
20.03.12
14:44
(29) Сдается мне это даже академическим интересом трудно считать. Смысла просто нет.
31 dmpl
 
20.03.12
14:44
(25) Да мне все равно, я такое сложение просто не буду использовать. Нигде.

(27) Кстати, а если попробовать явно использовать ВЫРАЗИТЬ()?
32 Axel2009
 
20.03.12
14:49
(30) академический есть. вон разобрали что происходит если в список значение разные типы данных задавать.. теперь все в курсе что так лучше не делать
33 vvp117
 
20.03.12
14:50
(28) почему не должны? Например, в SQL такая конструкция находится в рамках разумного, ну а в 1С, конечно, стоит подстраховаться.
(31) пробовал ВЫРАЗИТЬ, не помогло.
34 vvp117
 
20.03.12
14:51
(32) можно ссылку на тему? Интересно.
35 Axel2009
 
20.03.12
15:05
AdBlock убивает бесплатный контент. 1Сергей