Привязка данных к параметрам запроса:DatabaseBind/Array

После того как SQL-запрос был откомпилирован функцией DatabasePrepare, можно использовать полученный дескриптор запроса для привязки данных к параметрам запроса, для чего предназначены функции DatabaseBind и DatabaseBindArray. Обе функции можно вызывать не только сразу после создания запроса в DatabasePrepare, но и после сброса запроса в начальное состояние с помощью DatabaseReset (если запрос выполняется много раз в цикле).

Этап привязки данных требуется не всегда, поскольку подготовленные запросы могут и не иметь параметров. Как правило, такая ситуация возникает, когда запрос возвращает данные из SQL в MQL5, в связи с чем требуется дескриптор запроса: о том, как читать результаты запросов по их дескриптору, рассказано в разделах о функциях DatabaseRead/DatabaseReadBind и DatabaseColumn-функциях.

bool DatabaseBind(int request, int index, T value)

Функция DatabaseBind устанавливает для запроса с дескриптором request значение параметра с индексом index. По умолчанию нумерация начинается с 0, если параметры в запросе помечены подстановочными символами '?' (без номера). Однако, параметры могут обозначаться в строке запроса и с номером (?1, '?5', ?21): в таком случае фактические индексы, которые следует передавать в функцию, должны быть на 1 меньше, чем соответствующий номер в строке. Дело в том, что в строке запроса нумерация ведется с 1.

Например, для следующего запроса требуется задать один параметр (индекс 0):

int r = DatabasePrepare(db"SELECT * FROM table WHERE id=?");
DatabaseBind(r01234);

Если бы в строке запроса использовалась подстановка "... id=?10", потребовалось бы вызвать DatabaseBind с индексом 9.

Значение value в прототипе DatabaseBind может быть любого простого типа или строкой. Если параметру требуется сопоставить данные составного типа (структуры) или произвольные двоичные данные, которые можно представить в виде массива байтов, используйте функцию DatabaseBindArray.

Функция возвращает true в случае успеха, а иначе — false.

bool DatabaseBindArray(int request, int index, T &array[])

Функция DatabaseBindArray устанавливает для запроса с дескриптором request значение параметра с индексом index как массив простого типа или простых структур (включая строки). Эта функция позволяет записывать в базу данных BLOB и NULL (отсутствие значения, которое считается в SQL самостоятельным типом и не равно 0).

Вернемся к классу DBQuery в файле DBSQLite.mqh и поддержим в нем привязку данных.

class DBQuery
{
   ...
public:
   template<typename T>
   bool bind(const int indexconst T value)
   {
      return PRTF(DatabaseBind(handleindexvalue));
   }
   template<typename T>
   bool bindBlob(const int indexconst T &value[])
   {
      return PRTF(DatabaseBindArray(handleindexvalue));
   }
   
   bool bindNull(const int index)
   {
      static const uchar null[] = {};
      return bindBlob(indexnull);
   }
   ...
};

BLOB подойдет для переноса в базу любого файла в неизменном виде, например, если предварительно прочитать его в байтовый массив с помощью функции FileLoad.

Необходимость явной привязки значения NULL не так очевидна. Дело в том, что при вставке новых записей в базу вызывающая программа обычно передает только известные ей поля, а все недостающие (если они не помечены ограничением NOT NULL или не имеют иного значения DEFAULT в описании таблицы), "движок" автоматически оставит равными NULL. Однако при использовании подхода ORM бывает удобно записать в базу объект целиком, включая и поле с уникальным первичным ключом (PRIMARY KEY). В новом объекте этого идентификатора еще нет, так как его проставляет сама база при первой записи объекта, поэтому важно привязать это поле в новом объекте к значению NULL.