Работа с данными

Язык запросов

Поиск данных выполняется с помощью функций Query, QuerySimple, QueryObject:

void Query(string query, Message message);
void QuerySimple(string query, Message message);
void QueryObject(string query, Message message);
void Query(string query, PropertiesCollection parameters, Message message);
void QuerySimple(string query, PropertiesCollection parameters, Message message);
void QueryObject(string query, PropertiesCollection parameters, Message message);
void Query<T>(string query, IList<T> resultList);
void QuerySimple<T>(string query, IList<T> resultList);
void QueryObject<T>(string query, IList<T> resultList);
void Query<T>(string query, PropertiesCollection parameters, IList<T> resultList);
void QuerySimple<T>(string query, PropertiesCollection parameters, IList<T> resultList);
void QueryObject<T>(string query, PropertiesCollection parameters, IList<T> resultList);

где

  • string query - строка запроса,

  • PropertiesCollection parameters - параметры, передаваемые во WHERE,

  • IList<T> resultList или Message message - переменная, содержащая результаты поиска.

Для выполнения нескольких запросов в одном вызове реализованы методы Batch:

void QueryBatch(string query, PropertiesCollection parameters, params System.Collections.IList[] resultList)
void QueryObjectBatch(string query, PropertiesCollection parameters, params
System.Collections.IList[] resultList)
void QuerySimpleBatch(string query, PropertiesCollection parameters, params
System.Collections.IList[] resultList)

где

  • string query - все запросы, разделенные с помощью GO

  • PropertiesCollection parameters - параметры, передаваемые во WHERE

  • IList<T> resultList - переменные, содержащие результаты поиска

Примечание

В строке запроса поддерживается только конструкция SELECT.

Сложное поле далее по тексту - это поле типа Группа или Тип данных (с точки зрения банка они идентичны и хранятся одинаково).

Особенности поиска

Указание таблицы во FROM

В настоящее время поддерживаются в качестве имени таблицы только имена типов 1 уровня. Т.е. указание вложенных таблиц во FROM не реализовано. Например, такой запрос не выполнится:

SELECT ГородМассив.Object AS Город FROM Контрагент.ГородМассив AS ГородМассив

Возможность указывать поля и таблицы без алиасов, если они однозначны

Примеры:

SELECT Имя AS Имя FROM Контрагент AS Контрагент
SELECT Имя AS Имя FROM Контрагент
SELECT Имя FROM Контрагент

Выборка .Object

Может использоваться в операторе SELECT для выборки всех полей типа данных.

Примеры:

SELECT Контрагент.Object FROM Контрагент AS Контрагент
SELECT Контр.Object AS К FROM Контрагент AS Контр
SELECT Контрагент.Object FROM Контрагент AS Контрагент WHERE
Контрагент.EntityId='DD6C0E5A-B1F5-48CE-BEBC-02CC2398F71C'
SELECT Контрагент.Object, Контрагент.EntityId AS Id FROM Контрагент AS Контрагент
WHERE Контрагент.EntityId='DD6C0E5A-B1F5-48CE-BEBC-02CC2398F71C'
SELECT Контрагент.Object, Контрагент.Город.Object AS Город FROM Контрагент AS
Контрагент
SELECT Договор.Object, Договор.Условия.Продажи.Города.Object FROM Договор AS
Договор

Что следует учитывать:

  • используется только в SELECT;

  • это всегда последнее слово в пути;

  • .Object может стоять либо сразу после типа данных;

  • Либо после ссылки внутри нужного типа данных (причем у ссылки может быть IsArray=true или false);

  • может быть несколько таких объектов в одном SELECT;

  • результат запроса будет содержать все поля указанного типа данных, как если бы вы переписали их вручную через запятую;

  • можно использовать как с алиасом (через AS), так и без.

Выборка полей в SELECT

Можно указывать пути к любым полям из типа данных:

SELECT Договор.EntityId, Договор.Условия.Покупки.Товары.Название FROM Договор AS Договор
SELECT Договор.Условия FROM Договор AS Договор

Что следует учитывать:

  • можно использовать как с алиасом, так и без;

  • сложные поля разворачиваются в список дочерних полей;

  • ссылки разворачиваются в 2 поля - EntityId и DataTypeId.

Выборка ссылочных полей

Для полей ссылочного типа можно получить представление значения, хранящееся по ссылке с помощью ключевого слова VIEW.

SELECT VIEW(Контрагент) AS Представление FROM Контрагент AS Контрагент
SELECT VIEW(Контрагент.МестоРегистрации) AS Город FROM Контрагент AS Контрагент
SELECT VIEW(Контрагент.МестоРегистрации.Object) AS Город FROM Контрагент AS Контрагент

В качестве параметра по View может быть передана ссылка или объект (Object).

Представление строится согласно маске в поле Шаблон представления записи на вкладке Портал в типе данных. Если маска не заполнена, в качестве представления будет возвращено значение первого поля типа данных.

Выборка сложных ссылок

Для сложных ссылок (ссылок на несколько разных типов данных) можно указывать дополнительные фильтры по типу или интерфейсу:

SELECT Контрагент.МестоРегистрации.Object AS Город FROM Контрагент AS Контрагент
SELECT Контрагент.МестоРегистрации(Место).Object AS Место FROM Контрагент AS

Контрагент

SELECT Контрагент.МестоРегистрации(Город).Object AS Город FROM Контрагент AS Контрагент
SELECT Контрагент.МестоРегистрации(Город).ИсторияГорода.Object AS Город FROM Контрагент AS Контрагент
SELECT Контрагент.МестоРегистрации(Город).Object AS Город FROM Контрагент AS Контрагент
SELECT Контрагент.МестоРегистрации(Город).ИсторияГорода.Object AS Город FROM Контрагент AS Контрагент

Что следует учитывать:

  • если ничего не указывать - будут перебраны все типы данных ссылки;

  • если указать интерфейс - то из типов, на которые указывает ссылка, будут выбраны только те, которые реализуют указанный интерфейс;

  • если указать тип данных - то будут выбраны только ссылки указанного типа (по сути ссылка превращается в простую).

Поля в WHERE/OrderBy и прочих выражениях

Пути к полям можно также указывать в конструкциях WHERE/Order by и прочих аналогичных:

SELECT Контрагент.Object, Контрагент.ИНН AS п1, Контрагент.ИНН AS п2, Контрагент.EntityId AS п3 FROM Контрагент AS Контрагент WHERE Контрагент.Город.Название LIKE '%Моск%'

Что следует учитывать:

  • Если последнее поле в пути - ссылка, то сравнение будет по ReferenceId этой ссылки без учета DataTypeId.

  • Последним полем в таком пути не может быть сложное поле, так как оно состоит из нескольких полей.

Конструкция WHERE IS

В части WHERE можно для ссылок писать проверку, что ссылка указывает на нужный тип данных или интерфейс:

SELECT Контрагент.Object AS Город FROM Контрагент AS Контрагент WHERE Контрагент.МестоРегистрации IS (Город)

Что следует учитывать: данная проверка будет заменена на проверку DataTypeId у указанной ссылки.

Joins

SELECT Контрагент.Object,Контрагент.ИНН AS п1, Контрагент2.Город AS п2,
Контрагент2.EntityId AS п3 FROM Контрагент AS Контрагент LEFT JOIN Контрагент AS
Контрагент2 ON Контрагент.Город = Контрагент2.Город

Что следует учитывать:

  • можно писать их вручную. Поля и таблицы разворачиваются аналогично тому, что написано выше;

  • могут добавляться автоматически при обращении к массивам/ссылкам и прочим сложносоставным элементам. Автоматически сейчас всегда создается LEFT JOIN.

Конструкция IS

Возможно использование IS без WHERE, например в конструкциях с JOIN:

SELECT Контрагент.Object, Контрагент.ИНН AS п1, Контрагент2.Город AS п2,
Контрагент2.EntityId AS п3 FROM Контрагент AS Контрагент LEFT JOIN Контрагент AS
Контрагент2 ON Контрагент.Город = Контрагент2.Город AND Контрагент.МестоРегистрации
IS (Город)

Нечеткий поиск

В выражении WHERE можно использовать функцию для выполнения нашего нечеткого поиска:

SELECT Город.Object FROM Город AS Город WHERE SEARCH(Город.Название, 'Москва')
SELECT Город.Object FROM Город AS Город WHERE SEARCH(Город.Название, 'Москва', 1)
SELECT Город.Object FROM Город AS Город WHERE SEARCH(Город.Название, 'Москва', 1,
'Москва2')

Что следует учитывать:

  • Первый параметр - путь к простому полю, по которому нужно выполнить поиск.

  • Второй параметр - строка для поиска, которая будет передана в поисковый движок.

  • Третий параметр - допустимое количество ошибок при нечетком поиске, максимум 3. Задается опционально. По умолчанию значение 0 (т.е. ищем точно).

  • Четвертый параметр - строка для поиска, которая будет передана для поиска SQL с помощью LIKE.

  • Если в пути есть поле из другой таблицы банка - будет добавлен неявный JOIN.

  • Работает на нашем поисковом движке, который сначала ищет подходящие значения в своей памяти по индексам, а затем мы подставляем их в запрос или временную таблицу.

  • Данные запросы не кешируются, так как мы не отслеживаем изменения индекса поиска.

  • Если нечеткий поиск не настроен, то поиск будет выполнен в SQL по значению 4-го параметра (или второго, если четвертый не заполнен) с помощью конструкции LIKE.

Обновление данных UPDATE

Для обновления простых полей используется конструкция Update Set:

UPDATE Г SET Г.Название='Новая Москва', Г.Население=100500 FROM Город AS Г
WHERE Г.EntityId='00003000-0000-0000-0000-000000000000'
//или аналогично
UPDATE Город SET Название='Новая Москва', Население=100500 WHERE
EntityId='00003000-0000-0000-0000-000000000000'

Декларация переменных

Простая декларация

DECLARE @var BIGINT
DECLARE @var VARCHAR(200)

Декларация типов данных

DECLARE @var Город
DECLARE @var Место

Декларация с выборкой

DECLARE @Дог = SELECT DATA.Object AS договор FROM Договор AS DATA DECLARE @ArrayWords = SELECT M.Object FROM Местность AS M WHERE M.EntityId = „00000010-0000-0000-0000-000000000000“ DECLARE @arr1=SELECT ARRAY(M.МассивСлов AS МассивСлов) AS Слова FROM Местность AS M WHERE M.EntityId = „00000010-0000-0000-0000-000000000000“

Для всех переменных доступен SELECT

SELECT @Дог

Пакетное выполнение

Доступно выполнение нескольких запросов в одном обращении, разделенных оператором GO. Результатом запроса будет массив, содержащий два вложенных массива с результатами выборки:

SELECT М.Object AS Жители FROM Местность AS М GO SELECT К.Object AS Кагент
FROM Контрагент AS К

Результатом запроса будет массив с выборкой, с обновленными данными:

UPDATE Г SET Г.Название='Новая Москва', Г.Население=100500 FROM Город AS Г
WHERE Г.EntityId='00003000-0000-0000-0000-000000000000' GO SELECT DATA.Object
FROM Город AS DATA

Дополнительные функции

Проверка на заполненность ссылки

bool ISEMPTYLINK(путь к ссылочному полю)

Пример запроса:

SELECT История.Object AS ИсторииГорода FROM ИсторияГорода AS История WHERE
NOT ISEMPTYLINK(История.ИзвестноеМесто)

Проверка на существование объекта по указанной ссылке

bool ISEXISTS(путь к ссылочному полю)

Пример запроса:

SELECT Контрагент.Object FROM Контрагент AS Контрагент WHERE
isexists(Контрагент.МестоРегистрации)

Возвращает длину строки

NUMBER LEN(поле или строка)

Пример запроса:

SELECT Город.Название AS Название, Город.Население AS Количество,
len(Город.Название) AS Символов FROM Город AS Город WHERE len(Город.Название)=5

Возвращает подстроку от исходной строки

  • str - исходная строка

  • START - индекс начала подстроки

  • lenght - длина подстроки

  • string SUBSTRING(str,START,lenght)

Пример запроса:

SELECT Город.Название AS Название, Город.Население AS Количество,
SUBSTRING(Город.Название,1,1) AS Подстрока FROM Город AS Город WHERE
SUBSTRING(Город.Название,1,1)='К'

Сервисные возможности

Построенные в памяти дерево индексов можно выгрузить для анализа в файл с помощью запроса «toFile={Имя файла}»:

var textQuery = "toFile=1.json";
QueryObject(textQuery, dic, Результат);

Указанный файл будет помещен при выполнении запроса в каталог Банка данных: C:ProgramDataDatareonPlatformCacheDatareonPlatformDataBank.

Предупреждение

Выгружаются ВСЕ построенные деревья с индексом по всем объектам. Не рекомендуется выполнять запрос на большом количестве данных.

Нечеткий поиск

Для объектов предусмотрена возможность выполнения нечеткого поиска хранимых данных строкового типа. Для этого необходимо настроить индексы нечеткого поиска по соответствующим полям в разделе fuzzySearch конфигурации Типа данных. Пример конфигурации опубликован по адресу: https://localhost:7200/examples/any/dataType

Поиск выполняется с помощью разработанного для Платформы движка, строящий в памяти префиксное дерево.

При старте Банка данных система для полей, указанных в разделе fuzzySearch загружает из СУБД в память значения полей и EntityId записей. Из значений выделяются токены (слова), по символам токеновьстроится дерево. В терминальных узлах (последний символ токена) фиксируется EntityId записи и позиция токена в значении поля (фразе). В процессе построения индекса работа с данными Банка разрешена.

Нечеткий поиск выполняется с помощью специального метода SEARCH языка запросов.

Общие сведения:

  • Регистрозависимость: нет.

  • Разделение фразы на токены с помощью регулярного выражения.

  • Учет порядка токенов: да.

  • Использование wildcard: да (% _).

  • Лексический анализ: нет.

Правила поиска

Поиск выполняется всегда по токенам, а не по полному значению в искомом поле. Т.е. если в значении будет указана фраза «Раз два», то значение может быть найдено по слову «раз» или «два».

Wildcard

Заключается в использовании в поисковой строке спец символов:

  • _ Любой одиночный символ.

  • % Любая строка, содержащая ноль или более символов.

  • [] Любой одиночный символ, содержащийся в диапазоне ([a-f]) или наборе ([abcdef]).

  • [^] (НЕ РЕАЛИЗОВАНО, но планируется) Любой одиночный символ, не содержащийся в диапазоне ([^a-f]) или наборе ([^abcdef]).

Внимание

При использовании wildcard НЕ поддерживается поиск по фразе (несколько токенов через пробел) и нечеткий поиск.

Нечеткий поиск

Заключается в поиске данных с допущением, что часть символов может не совпадать. Количество символов, которые могут не совпадать, передается в виде параметра в методе SEARCH языка запросов. Допустимые значения параметра: 0-3.