Для формирования и выполнения запросов к таблицам базы данных в платформе 1С используется специальный объект языка программирования Запрос. Создается этот объект вызовом конструкции Новый Запрос. Запрос удобно использовать, когда требуется получить сложную выборку данных, сгруппированную и отсортированную необходимым образом. Классический пример применения запроса - получение сводки по состоянию регистра накопления на определенный момент времени. Так же, механизм запросов позволяет легко получать информацию в различных временных разрезах.
Текст запроса – это инструкция, в соответствии с которой должен быть выполнен запрос. В тексте запроса описывается:
таблицы информационной базы, используемые в качестве источников данных запроса;
поля таблиц, которые требуется обрабатывать в запросе;
правила группировки;
сортировки результатов;
и т. д.
Инструкция составляется на специальном языке – языке запросов и состоит из отдельных частей – секций, предложений, ключевых слов, функций, арифметических и логических операторов, комментариев, констант и параметров.
Язык запросов платформы 1С очень похож на синтаксис других SQL-языков, но имеются отличия. Основными преимуществами встроенного языка запросов являются: разыменование полей, наличие виртуальных таблиц, удобная работа с итогами, нетипизированные поля в запросах.
Рекомендации по написанию запросов к базе данных на языке запросов платформы 1С:
1) Текст запроса может содержать предопределенные данные конфигурации, такие как:
значения перечислений;
предопределенные данные:
справочников;
планов видов характеристик;
планов счетов;
планов видов расчетов;
пустые ссылки;
значения точек маршрута бизнес-процессов.
Также текст запроса может содержать значения системных перечислений, которые могут быть присвоены полям в таблицах базы данных: ВидДвиженияНакопления, ВидСчета и ВидДвиженияБухгалтерии. Обращение в запросах к предопределенным данным конфигурации и значениям системных перечислений осуществляется с помощью литерала функционального типа ЗНАЧЕНИЕ. Данный литерал позволяет повысить удобочитаемость запроса и уменьшить количество параметров запроса.
Пример использования литерала ЗНАЧЕНИЕ:
ГДЕ Город = ЗНАЧЕНИЕ(Справочник.Города.Москва)
ГДЕ Город = ЗНАЧЕНИЕ(Справочник.Города.ПустаяСсылка)
ГДЕ ТипТовара = ЗНАЧЕНИЕ(Перечисление.ВидыТоваров.Услуга)
ГДЕ ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
ГДЕ ТочкаМаршрута = ЗНАЧЕНИЕ(БизнесПроцесс.БизнесПроцесс1.ТочкаМаршрута.Действие1
2) Использование инструкции АВТОУПОРЯДОЧИВАНИЕ в запросе может сильно время выполнения запроса, поэтому, если сортировка не требуется, то лучше вообще ее не использовать. Во большинстве случаях лучше всего применять сортировку с помощью инструкции УПОРЯДОЧИТЬ ПО.
Автоупорядочивание работает по следующим принципам:
Если в запросе было указано предложение УПОРЯДОЧИТЬ ПО, то каждая ссылка на таблицу, находящаяся в этом предложении, будет заменена полями, по которым по умолчанию сортируется таблица (для справочников это код или наименование, для документов – дата документа). Если поле для упорядочивания ссылается на иерархический справочник, то будет применена иерархическая сортировка по этому справочнику.
Если в запросе отсутствует предложение УПОРЯДОЧИТЬ ПО, но есть предложение ИТОГИ, тогда результат запроса будет упорядочен по полям, присутствующим в предложении ИТОГИ после ключевого слова ПО, в той же последовательности и, в случае если итоги рассчитывались по полям – ссылкам, то по полям сортировки по умолчанию таблиц, на которые были ссылки.
Если в запросе отсутствуют предложения УПОРЯДОЧИТЬ ПО и ИТОГИ, но есть предложение СГРУППИРОВАТЬ ПО, тогда результат запроса будет упорядочен по полям, присутствующим в предложении, в той же последовательности и, в случае если группировка велась по полям – ссылкам, то по полям сортировки по умолчанию таблиц, на которые были ссылки.
В случае же, если в запросе отсутствуют предложения и УПОРЯДОЧИТЬ ПО, ИТОГИ и СГРУППИРОВАТЬ ПО, результат будет упорядочен по полям сортировки по умолчанию для таблиц, из которых выбираются данные, в порядке их появления в запросе.
В случае, если запрос содержит предложение ИТОГИ, каждый уровень итогов упорядочивается отдельно.
3) Что бы избежать повторного запроса к базе данных при выводе результата запроса пользователю (например, построение запроса или отображение результата запроса с помощью табличного документа) полезно использовать инструкцию ПРЕДСТАВЛЕНИЕССЫЛКИ, которая позволяет получать представление ссылочного значения. Пример:
Так же возможно использование инструкции ПРЕДСТАВЛЕНИЕ - предназначена для получения строкового представления значения произвольного типа. Отличие этих инструкций в том, что в первом случае, если инструкции передать ссылку, результатом будет строка, В остальных случаях результатом будет значение переданного параметра. Во втором случае, результатом инструкции всегда будет строка!
4) Если в запросе имеется поле с составным типом, то для таких полей возникает необходимость привести значения поля к какому-либо определенному типу с помощью инструкции ВЫРАЗИТЬ, что позволит убрать лишние таблицы из левого соединения с полем составного типа данных и ускорить выполнение запроса. Пример:
Имеется регистра накопления ОстаткиТоваров, у которого поле Регистратор имеет составной тип. В запросе выбираются Дата и Номер документов ПоступлениеТоваров, при этом при обращении к реквизитам документа через поле Регистратор не происходит множество левых соединений таблицы регистра накопления с таблицами документов-регистраторов.
Если приведение типа считается не осуществимым, то результатом приведения типа будет значение NULL.
5) Не стоит забывать про инструкцию РАЗРЕШЕННЫЕ, которая означает, что запрос выберет только те записи, на которые у текущего пользователя есть права. Если данное слово не указать, то в случае, когда запрос выберет записи, на которые у пользователя нет прав, запрос отработает с ошибкой.
6) В случае, если в запросе используется объединение, и в некоторых частях объединения присутствуют вложенные таблицы (документ с табличной частью), а в некоторых нет, возникает необходимость дополнения списка выборки полями – пустыми вложенными таблицами. Делается это при помощи ключевого слова ПУСТАЯТАБЛИЦА, после которого в скобках указываются псевдонимы полей, из которых будет состоять вложенная таблица. Пример:
7) Что бы в результат запроса не попали повторяющиеся строки, следует использовать инструкцию РАЗЛИЧНЫЕ, потому что так нагляднее и понятнее, а инструкция СГРУППИРОВАТЬ ПО применяется для группировки с помощью агрегатных функций. Ксати, при использовании агрегатных функций предложение СГРУППИРОВАТЬ ПО может быть и не указано совсем, при этом все результаты запроса будут сгруппированы в одну единственную строку. Пример:
8) Инструкция СГРУППИРОВАТЬ ПО позволяет обращаться к полям верхнего уровня, без группировки результатов по этим полям, если агрегатные функции применены к полям вложенной таблицы. Хотя в справке 1С написано, при группировке результатов запроса в списке полей выборки обязательно должны быть указаны агрегатные функции, а помимо агрегатных функций в списке полей выборки допускается указывать только поля, по которым осуществляется группировка. Пример:
9) Инструкция ЕСТЬNULL предназначена для замены значения NULL на другое значение, но не забываем, что второй параметр будет преобразован к типу первого в случае, если тип первого параметра является строкой или числом.
10) При обращении к главной таблице можно в условии обратиться к данным подчиненной таблицы. Такая возможность называется разыменование полей подчиненной таблицы.
Пример (поиск документов, содержащих в табличной части определенный товар):
Преимущество этого запроса перед запросом к подчиненной таблице Приходная.Товары в том, что если есть дубли в документах, результат запроса вернет только уникальные документы без использования ключевого слова РАЗЛИЧНЫЕ.
11) Интересный вариант оператора В - это проверка вхождения упорядоченного набора в множество таких наборов (Поле1, Поле2, ... , ПолеN) В (Поле1, Поле2, ... , ПолеN).
Пример:
12) При любой возможности используйте виртуальные таблицы запросов. При создании запроса система предоставляет в качестве источников данных некоторое количество виртуальных таблиц - это таблицы, которые так же являются результатом запроса, который система формирует в момент выполнения соответствующего участка кода.
Разработчик может самостоятельно получить те же самые данные, которые система предоставляет ему в качестве виртуальных таблиц, однако алгоритм получения этих данных не будет оптимизирован, так как:
Все виртуальные таблицы параметризованы, т. е. разработчику предоставляется возможность задать некоторые параметры, которые система будет использовать при формировании запроса создания виртуальной таблицы. В зависимости от того, какие параметры виртуальной таблицы указаны разработчиком, система может формировать РАЗЛИЧНЫЕ запросы для получения одной и той же виртуальной таблицы, причем они будут оптимизированы с точки зрения переданных параметров.
Не всегда разработчик имеет возможность получить доступ к тем данным, к которым имеет доступ система.
13) В клиент-серверном варианте работы функция ПОДСТРОКА() реализуется при помощи функции SUBSTRING() соответствующего оператора SQL, передаваемого серверу баз данных SQL Server, который вычисляет тип результата функции SUBSTRING() по сложным правилам в зависимости от типа и значений ее параметров, а так же в зависимости от контекста, в котором она используется. В большинстве случаев эти правила не оказывают влияния на выполнение запроса, но бывают случаи, когда для выполнения запроса существенна максимальная длина строки результата, вычисленная SQL Server. Важно иметь в виду, что в некоторых контекстах использования функции ПОДСТРОКА() максимальная длина ее результата может оказаться равной максимальной длине строки ограниченной длины, которая в SQL Server равна 4000 символам. Это может привести к неожиданному аварийному завершению выполнения запроса:
Microsoft OLE DB Provider for SQL Server: Warning: The query processor could not produce a query plan from the optimizer because the total length of all the columns in the GROUP BY or ORDER BY clause exceeds 8000 bytes.
HRESULT=80040E14, SQLSTATE=42000, native=8618
Чтобы избежать такой ошибки, не рекомендуют использовать функцию ПОДСТРОКА() с целью приведения строк неограниченной длины к строкам ограниченной длины. Вместо нее лучше использовать операцию приведения типа ВЫРАЗИТЬ().
14) С осторожностью используйте ИЛИ в конструкции ГДЕ, так как использование условия с ИЛИ может значительно "утяжелить" запрос. Решить проблему можно конструкцией ОБЪЕДИНИТЬ ВСЕ. Пример:
15) Условие НЕ В в конструкции ГДЕ увеличивает время исполнения запроса, так как это своего рода НЕ (ИЛИ1 ИЛИ2 ... ИЛИn), поэтому для больших таблиц старайтесь использовать ЛЕВОЕ СОЕДИНЕНИЕ с условием ЕСТЬ NULL. Пример:
16) При использовании Временных таблиц нужно индексировать поля условий и соединений в этих таблицах, НО, при использовании индексов запрос может выполняться еще медленнее. Поэтому необходимо анализировать каждый запрос с применением индекса и без, замерять скорость выполнения запроса и принимать окончательное решение.
Если вы помещаете во временную таблицу данные, которые изначально индексированы по некоторым полям, то во временной таблице индекса по этим полям уже не будет.
17) Если вы не используете Менеджер временных таблиц, то явно удалять временную таблицу не требуется, она будет удалена после завершения выполнения пакетного запроса, иначе следует удалить временную таблицу одним из способов: командой УНИЧТОЖИТЬ в запросе, вызвать метод МенеджерВременныхТаблиц.Закрыть().
В этой статье я расскажу, как загружать данные в 1с 8 из простейших текстовых файлов с разделителями. Обычно они имеют расширение csv (Comma-Separated Values). Т. е. название подразумевает, что в каждой строке такого текстового файла значения разделены запятой. Но на самом деле, запятую, в качестве разделителя, использовать не надёжно. Поэтому применяют другие разделители, которые в обычном тексте встречаются редко. Это могут быть символы «^», «~»,«|» и другие. Итак, наша задача состоит в том, чтобы загрузить имеющуюся в csv файле информацию в базу данных 1с. Например, в файле будут содержаться товары интернет - магазина. В качестве образца, я взял выгрузку из магазина на скрипте virtuemart. Посмотрим, как выглядит файл.
Привожу две первых строки из него:
Посмотрим на файл.
Первая строка служебная. В ней описан формат нашего файла. Т. е. в какой ячейке, что находится. Однако, имейте в виду, что такой строки может и не быть.
Ячейки образуются при помощи разделителя «^», а данные в ячейках обрамляются символом «~».
В любой конфигурации 1с есть иерархический справочник товаров. В него и будем загружать информацию.
Создадим внешнюю обработку. Добавим строковый реквизит «путьКФайлуЗагрузки» для хранения имени файла. Добавим на форму поле ввода, связанное с данным реквизитом. Включим в свойствах поля ввода кнопку выбора и создадим обработчик события «НачалоВыбора» и напишем в нём такой код:
Т. о. мы организовали диалог для выбора файла в нашей обработке.
Хорошо. Теперь, для удобства и наглядности я предлагаю создать временную табличку, в которую мы загрузим текстовый файл, а уже после её заполнения - будем осуществлять загрузку в базу 1с. Для этого, на форму добавим табличное поле «табЗагрузки», с типом значения «ТаблицаЗначений» и командной панелью. В панели поместим кнопку «Заполнить» и создадим обработчик её нажатия «КоманднаяПанель1Заполнить». Также для элемента универсальности, добавим в обработку два строковых реквизита «символОграничения» и «разделительПолей». В них мы будем хранить «^», и «~». Можно в теле модуля формы осуществить их начальную инициализацию:
разделительПолей = "^";
символОграничения = "~";
Это позволит пользователю задать свои значения и при желании сохранить настройку, которая впоследствии не затрется нашей инициализацией.
Функцию разложения строки с разделителями в массив можно разместить как в одном из общих модулей, так и непосредственно в обработке.
Отлично. В итоге, после заполнения, получим примерно такую картинку:
Теперь приступим непосредственно к загрузке товаров. Рядом с кнопкой «заполнить» добавим кнопку «загрузить» и добавим обработчик её нажатия «КоманднаяПанель1Загрузить», а также добавим реквизит «ПапкаЗагрузкиВыгрузкиТоваров» с типом вашего справочника товаров для опциональной их загрузки в определенную папку. Текст обработчика будет такой:
В приведенном коде две новые функции «вернутьТовар» и «ЗаписатьЭлементСпр». Вот их текст:
И осталась последняя новая функция для обработки родителя товара вернутьРодителяТовара. Текст её смотрите ниже. Комментарии по тексту.
Событие ПриПолученииДанных использется для оформления ячеек строк данных, отображаемых табличным полем. Обработчик данного события вызывается табличным полем в тех же случаях, что и обработчик ПриВыводеСтроки, т.е. при обновлении данных, отображаемых табличным полем или при поиске по подстроке. Важно отметить, что обработчик данного события вызывается табличным полем перед вызовом обработчиков события ПриВыводеСтроки для всех видимых строк табличного поля. Основным отличием данного события от события ПриВыводеСтроки является то, что в обработчике события ПриПолученииДанных можно изменять настройки ячеек группы строк, а не одной строки как в обработчике события ПриВыводеСтроки.
Обрабатывая данное событие можно изменять шрифт, цвет фона или текста, как определенной ячейки, так и всей строки табличного поля, устанавливать высоту или видимость ячеек строки табличного поля, а также устанавливать картинку, флажок или новый текст в ячейке. Параметром данного события является объект типа ОформлениеСтрок - коллекция объектов типа ОформлениеСтроки, являющихся оформлениями строк табличного поля.
Важно отметить, что в некоторых случаях обработчик события ПриПолученииДанных может вызываться табличным полем более одного раза. Например, если текущая строка табличного поля находится в середине видимой области, то при обновлении обработчик события ПриПолученииДанных будет вызван табличным полем два раза: первый раз для группы строк, начиная с текущей строки до верхней видимой и второй раз для строки, следующей за текущей до нижней видимой строки. Такое поведение табличного поля связано с тем, что при обновлении табличное поле пытается сохранить позицию текущий строки в видимой области.
Поясним использовании события ПриПолученииДанных на следующем примере. Пусть существует форма списка справочника "Номенклатура" с двумя табличными полями. Пусть одно из табличных полей отображает указанный список справочника как дерево, а другое как иерархический список. Требуется в табличном поле, отображающем данные как иерархический список, отображать остатки по позициям номенклатуры.
Наиболее эффективным способом решения данной задачи является использование события ПриПолученииДанных. В обработчике данного события формируется запрос к регистру накопления "УчетНоменклатуры" для получения остатков. В качестве параметра данного запроса передается массив, содержащий ссылки на отображаемые строки табличного поля. Затем выполняется запрос и получается выборка. Полученная выборка обходится и значения остатков устанавливаются в ячейке "Остаток".
Когда справочник наполняется помеченными на удаление объектами, они начинают мешать пользователям выбирать значение справочника. Бывает, что долго не представляется возможным удалить помеченные на удаление элементы. Чтобы пользователям они не мешали, можно программным путем отключить их видимость при открытии формы выбора (или формы списка) справочника с помощью предустановки отбора.
Делается это примерно таким способом. В диалоговой форме справочника назначается процедура «При открытии». И в модуле формы пишется примерно такой код:
Есть ли в 8.х аналог ИспользоватьСписокЭлементов?
В динамических списках документов, справочников и т.д. может быть программно установлен отбор по полю Ссылка с указанием в качестве вида сравнения вхождения в список значений. Это позволяет отображать в списке только определенные объекты.
Однако эта возможность может иметь только ограниченное применение, так как динамический список имеет достаточно большое количество универсальных возможностей (установка отбора пользователем, переходы по уровням в иерархических списках и т.д.) и совмещение в прикладных решениях этих механизмов с отбором по конкретным значениям ссылок достаточно сложно реализуется.
В большинстве случаев, если необходимо обеспечить отображение в списке специально отобранного перечня объектов, можно рекомендовать использовать другие возможности (например, выборку данных запросом и отображение в форме с помощью таблицы значений или табличного документа). При этом система обеспечивает возможность полноценного взаимодействия с такими формами других системных механизмов.
Для 7.7 используем метод ИспользоватьСписокЭлементов
Автор: Antoska
Для решения данной задачи я решил воспользоваться методом формы списка "ИспользоватьСписокЭлементов(<СписокЗначений>)", так как использование процедуры "ОбработкаПодбора()" требует наличия реквизита справочника для отбора, а это мне не очень подходит. Вот как я реализовал этот алгоритм (код из модуля формы списка справочника):
Функцией "СоответствуетУсловиямФильтра(ЭлементСправочника)" можно задавать любые условия фильтрации списка опираясь на передаваемый ей элемент справочника.
Скорость работы приемлема, но можно попробовать реализовать и через запрос...
Порядок действий такой:
1. В поле ввода "Номенклатура" добавь событие ПриНачалеВыбора.
2. Установи в них СтандартнаяОбработка = Ложь;
3. Получи форму выбора нужного справочника
4. Установи отбор по родителю
5. Открой форму для выбора
Теперь подробнее:
Заходим в Свойства реквизита - для которогу нужно настроить выбор из группы, это может быть реквизит табличной части или просто реквизит на форме, и Задаем Событие - Начало Выбора
Для вывода иерархического справочника в отчет с сохранением иерархии необходимо пользоваться запросом аналогичным следующему:
Данный запрос выбирает все записи из справочника и производит упорядочивание по иерархии. Результат будет упорядочен по наименованию, с учетом иерархии.
Для того чтобы группы справочника размещались выше элементов необходимо в данном запросе заменить предложение УПОРЯДОЧИТЬ ПО на следующее:
Результат по-прежнему будет упорядочен по иерархии, однако группы будут располагаться выше элементов.
Возможна также замена предложения УПОРЯДОЧИТЬ ПО на предложение АВТОУПОРЯДОЧИВАНИЕ. В этом случае результат будет упорядочен в соответствии с настройками справочника, т.е. если в справочнике указано, что группы должны располагаться выше элементов, то они будут расположены выше.
Получить иерархическую структуру справочника также возможно и при помощи итогов.
Для удаления всех элементов справочника можно использовать объект СправочникВыборка.<имя>, с помощью которого осуществлять обход и удаление всех элементов справочника. При этом следует учитывать, что если справочник иерархический, то выборка должна быть также иерархической, так как при удалении элемента удаляются и все его подчиненные элементы. Например:
Результат запроса может быть выгружен в таблицу значений или дерево значений с помощью метода Выгрузить. Затем над ними могут быть произведены другие операции: сортировка, свертка, перебор строк и другие действия.
Следующий пример выгружает результат запроса в таблицу значений с прямым порядком обхода строк:
Если используется иерархический обход результата запроса или обход по группировкам, тогда удобнее выгрузить не в таблицу значений, а в дерево значений, как делается в следующем примере:
Новый элемент или группу в справочник нельзя добавить если выключен режим иерархического списка. Для того, чтобы включить этот режим выберите в меню "Действия" пункт "Иерархический список" и установите этот режим.