Работа с датой
Знал бы, где упасть – соломки бы подстелил
(Народная мудрость)
Довелось в практической деятельности разработчика в “1С:Підприємство” столкнуться со следующим явлением. В базе было создано наперед несколько тысяч объектов справочника «Информационные карты» – для последующего занесения в них и хранения информации о постоянных покупателях торговой сети. Объектов было создано примерно 10 тысяч, на момент возникновения инцидента заполнено данными было около 7 тысяч карт. Каждое утро одно регламентное задание находило именинников среди клиентов сети (данные о которых были занесены в базу), а другое рассылало им поздравительные СМС с приглашениями получить подарок в любом удобном покупателю магазине. Запрос, который выбирал именинников из общей массы, имел приблизительно следующий вид:
1 2 3 4 5 6 7 8 9 10 11 |
ЗапросИменинников = Новый Запрос; ЗапросИменинников.Текст = “Выбрать | ИнформационныеКарты.Ссылка | ГДЕ | День(ИнформационныеКарты.ДатаРожденияКлиента) = &День | И Месяц(ИнформационныеКарты.ДатаРожденияКлиента) = &Месяц”; |
На место параметров «День» и «Месяц» подставлялись соответствующие день и месяц текущего дня. Всё шло своим чередом, именинников в среднем находилось по 10-20 с периодическими всплесками до 30, но тут наступило 1е января. Регламент вдруг посчитал нужным поздравить почти 3 тысячи человек (к счастью, телефоны были указаны только у 300 из этого количества).
Анализ ситуации показал, что причиной такого поведения процедуры стало своеобразное понимание понятия NULL создателями среды “1С:Підприємство” (а также нежелание привести это понимание к общему знаменателю с пониманием этого у авторов языка запросов SQL).
В данном конкретном случае дело было в следующем. Даже незаполненное данными поле типа ДАТА вовсе не равно NULL, как можно было бы подумать. Среда “1С:Підприємство” в пустое поле ДАТА записывает значение Дата(“00010101”), то есть 1 января 0001-го года (видимо, нашей эры, хотя я не был бы столь уверен – имея опыт работы с “1С:Підприємство” больше недели), при этом никак не отражая это на форме. В то же время – хотя какие-то данные в поле (и соответствующую ячейку памяти) записаны, функция ЗначениеЗаполнено(Дата) возвращает Ложь. Это обстоятельство стоит учитывать при разработке операций с датами (хотя тип ДАТА вовсе не единственный, где NULLи не заполненное значение вовсе не тождественны) – во избежание подобных затруднений.
Конкретно в данном случае можно либо при обработке результатов запроса проверять значение ДатаРожденияКлиента на заполненность (что менее производительно), либо задавать в запросе отбор еще и по году рождения клиента (например с 1800 – чтобы наверняка)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
ЗапросИменинников = Новый Запрос; ЗапросИменинников.Текст = “Выбрать | ИнформационныеКарты.Ссылка | ГДЕ | День(ИнформационныеКарты.ДатаРожденияКлиента) = &День | И Месяц(ИнформационныеКарты.ДатаРожденияКлиента) = &Месяц | И Год(ИнформационныеКарты.ДатаРожденияКлиента) > 1800”; |
Автор: Виталий Моргун
Leave a Reply