Содержание
Внутренний язык запросов
Внутренний язык запросов очень похож на SQL, но он намного более нагляден, чем языки баз данных благодаря следующим упрощениям и расширениям:
Язык запросов SQL-сервера
Вы можете использовать язык запросов SQL-сервера совместно с внутренним языком запросов (функция DirectQuery). Но вы усложняете разработку, и в том числе усложняете возможность переноса вашей базы данных на другой тип SQL сервера. Например MySQL -> SQLite. Запросы на внутреннем языке транслируются в запросы используемого SQL сервера с учетом его особенностей, поэтому работают идентично на любом SQL сервере.
Типы данных
Язык запросов строго типизирован. То есть вы не сможете сложить строку и число.
Набор типов данных языка запросов такой же как в языке программирования. За исключением того, что в БД не могут сохраняться объекты (указатель на объект в памяти). А в языке программирования строки и числа не могут принимать значение NULL.
В основном это сделано для безопасных финансовых расчетов. Тип данных Float округляется (но может принимать больший диапазон значений). Тип данных Currency никогда не округляется. Даже деление 1/3 вызовет ошибку. И платформа не допускает смешивания типов Currency и Float.
Для деления и умножения Currency можно использовать функции RoundMul, RoundDiv третьим аргументов которых указывается точность. Простым поиском RoundMul, RoundDiv в гигантской программе можно легко причину потери точности.
Автоподстановка и проверка запросов во время ввода
Проверка корректности запросов, наличия полей в базе данных, типов данных полей производится прямо во время ввода программы. Редактор сразу же предлагает список полей, функций, переменных и т.п. Так же запросы проверяется при запуске программы.
То есть, еще до начала работы с программы вы находите большинство глупых ошибок.
При запуске программы, запросы преобразуются в язык используемого SQL сервера. Это увеличивает скорость работы.
Параметры SQL-запросов
Запросы пишутся не в виде строки, а прямо в коде программы. А параметры (внешние данные) в запрос передаются с помощью оператора двоеточие.
(Insert Into Client(Name) Values(:N));
Это позволяет упростить запрос, то есть повысить наглядность и надежность. Полностью исключает глупые ошибки типа SQL Infection. А так же позволяет произвести контроль типов. То есть, если переменная N будет числового типа, поле Name таблицы БД будет строкового, то запрос будет подчеркнут красной линией и программа не запустится.
Причем, после : можно указывать не только переменную, но и любое выражение языка программирования. Включая SQL-запросы (они то же являются выражением)
(Insert Into Client(Name) Values(:LocalFunction(LocalVar)));
Запросы можно выполнять и из строки с помощью функции Query
AUTOJOIN
Вот пример типичного запроса для MySQL. Даже несколько упрощенного для наглядности.
Select Client.Name, City.Name, Country.NameFrom Client Left Outer Join City on City.Code=Client.City Left Outer Join City BornCity on BornCity.Code=Client.BornCity
Есть справочник клиентов (Client), в котором есть поле город (City). Поле город ссылается на справочник городов (City), в котором есть поле страна (Country). Что бы нам получить информацию о стране, в которой родился клиент, нам нужно написать такой запрос с двумя JOIN-ами.
Почему это плохо?
1) Слишком много текста. Снижается наглядность и надежность.
2) Части запроса не изолированы между собой. То есть вы не можете просто добавить или удалить выражение между SELECT и FROM. Надо обязательно просматривать все JOIN-ы. И изменение какого то JOIN-а сломает все запросы.
При этом, база данных "знает" что поле City ссылается на таблицу City. То есть она могла бы сама формировать JOIN-ы.
И внутренний SQL это делает, вот аналогичный запрос:
Select Name, City.Name, City.Country.Name From Client
Как вы видите, подучить доступ к полям зависимой таблицы можно с помощью точки. Все JOIN-ы сформирует сама платформа.
А неоднозначных и сложных случаях, вместо JOIN-а платформа использует подзапрос.
CAST(... AS *таблица)
С любым значением или выражением можно работать как с полем ссылкой, используя оператор CAST(... AS *таблица)
Например:
Cast(IntegerField As *Client).Name
Cast(2 As *Client).Name
Оптимизатор запросов
Внутренний язык запросов предельно упрощен, но при этом он позволяет выполнить 99% работы. А для типовых задач все сто. Зачем же существуют более сложные формы? Только лишь для скорости.
Но сложность и наглядность таких быстрых запросов, часто заставляет программиста часами читать форумы и обращаться за помощью. Это значительно снижает надежность программы и увеличивает время разработки и последующей поддержки.
Поэтому платформа предлагает компромиссное решение. Программист сначала пишет простой и понятный запрос на внутреннем языке, а если скорость его работы не устраивает, то с помощью отдельного инструмента "Оптимизатора запросов" производится его ускорение.
p>Программист в этом "Оптимизаторе запросов" определяет пары запросов - меленный и быстрый. В программе всё так же остается понятный запрос, но работает уже быстрый. Программа остается понятной!При этом, оптимизатор позволяет в автоматическом режиме проверить идентичность результатов запросов. То есть более простым запросом проверить более медленный. Оптимизатор - это не только ускорение, но еще один рубеж проверки, а следовательно надежности программы.