При длительной эксплуатации конфигураций на платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ситуацией, когда проверенный годами код выборки данных журнала расчетов внезапно перестает работать. Цикл обхода записей просто игнорируется, хотя входные параметры заполнены корректно. При этом в файловой (DBF) копии базы данных или в архивных копиях тот же самый код отрабатывает без нареканий.
Проанализируем типовой фрагмент кода, в котором возникает ошибка:
ЖЗП.ВыбратьПоЗначению("Подразделение", ТекПодр, ДН, ДК);
Пока ЖЗП.ПолучитьЗапись() = 1 Цикл
// Обработка записей журнала расчетов
КонецЦикла;
Выясним причину такого поведения платформы при работе с Microsoft SQL Server и разберем практические способы решения этой проблемы.
Разница в поведении между файловым движком и клиентом MS SQL Server кроется в механизмах трансляции платформенных команд в запросы к СУБД:
ВыбратьПоЗначению в качестве параметров интервала выборки ожидает специальные агрегатные объекты расчетного периода. В файловом режиме (DBF) внутренний обработчик платформы часто выполняет неявное приведение обычной даты к расчетному периоду. Однако на стороне SQL платформа генерирует прямой запрос к таблице журнала расчетов (CJ*). Если передана дата, а не период, транслятор условий формирует некорректный фильтр по границам действия записей, из-за чего результирующий набор данных оказывается пустым.ТекПодр передается группа справочника, прямое сравнение на уровне СУБД не находит вхождений, так как автоматическое разворачивание иерархии в данном методе не выполняется.1CV7.DDS и базой данных MS SQL Server выборка по индексированной графе журнала перестает возвращать строки.Разберем первый и самый надежный способ исправления платформенного вызова. Преобразуем стандартные переменные даты начала и даты окончания в объекты расчетного периода с помощью метода ПериодПоДате() самого журнала расчетов.
Посмотрим на пример правильного вызова:
ПерНач = ЖЗП.ПериодПоДате(ДН);
ПерКон = ЖЗП.ПериодПоДате(ДК);
// Проверяем, что передается элемент, а не группа справочника
Если (ПустоеЗначение(ТекПодр) = 0) И (ТекПодр.ЭтоГруппа() = 0) Тогда
ЖЗП.ВыбратьПоЗначению("Подразделение", ТекПодр, ПерНач, ПерКон);
Пока ЖЗП.ПолучитьЗапись() = 1 Цикл
// Обработка записей журнала
КонецЦикла;
КонецЕсли;
Если требуется получить выборку строго в рамках одного расчетного периода, передадим один и тот же объект периода в качестве начальной и конечной границы:
ТекПер = ЖЗП.ПериодПоДате(ДН);
ЖЗП.ВыбратьПоЗначению("Подразделение", ТекПодр, ТекПер, ТекПер);
Пока ЖЗП.ПолучитьЗапись() = 1 Цикл
// Обработка записей журнала
КонецЦикла;
Если в силу специфики структуры базы отбор по графе журнала на стороне SQL продолжает сбоить, заменим проблемный метод штатной выборкой по периоду. В таком случае отбор по необходимому значению реквизита или графы выполним явным условием внутри цикла.
Рассмотрим реализацию данного обходного пути:
ПерНач = ЖЗП.ПериодПоДате(ДН);
ПерКон = ЖЗП.ПериодПоДате(ДК);
ЖЗП.ВыбратьПериод(ПерНач, ПерКон);
Пока ЖЗП.ПолучитьЗапись() = 1 Цикл
// Фильтруем записи по значению подразделения
Если ЖЗП.Подразделение <> ТекПодр Тогда
Продолжить;
КонецЕсли;
// Полезный код обработки записи
КонецЦикла;
Данный вариант полностью устраняет зависимость от внутреннего механизма выборки по значению графы журнала на сервере СУБД.
Альтернативным и более производительным решением для больших объемов данных является использование объекта Запрос. Встроенный язык запросов 1С 7.7 корректно транслирует условия отбора в синтаксис T-SQL без сбоев на уровне агрегатных периодов.
Посмотрим, как построить такой запрос:
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ВыборкаЖР)
|Период С ДН По ДК;
|ТекущаяЗапись = ЖурналРасчетов.Зарплата.ТекущаяЗапись;
|Подр = ЖурналРасчетов.Зарплата.Подразделение;
|Группировка ТекущаяЗапись;
|Условие(Подр = ТекПодр);
|"//}}ЗАПРОС
;
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
Пока Запрос.Группировка("ТекущаяЗапись") = 1 Цикл
// Доступ к текущей записи журнала через Запрос.ТекущаяЗапись
КонецЦикла;
КонецЕсли;
Если замена кода нежелательна, а сбой выборки возник внезапно без изменения конфигурации (файла 1cv7.md), выполним административное обслуживание базы данных:
CJ* и полностью перестроит индексы в соответствии с описанием метаданных.
-- Обновление статистики для базы
EXEC sp_updatestats;