DatabasePrepare

Создает хендл запроса, который затем может быть исполнен с помощью DatabaseRead().

int  DatabasePrepare(
   int     database,      // хендл базы данных, полученный в DatabaseOpen
   string  sql,           // SQL-запрос
           ...            // параметры запроса
   );

Параметры

database

[in]  Хендл базы данных, который получен в DatabaseOpen().

sql

[in]  SQL запрос, который может содержать автоподставляемые параметры с именами ?1,?2,...

...

[in]  Автоматически подставляемые параметры запроса.

Возвращаемое значение

При успешной выполнении возвращает хэндл на SQL-запрос, в противном случае возвращает INVALID_HANDLE. Для получения кода ошибки используйте GetLastError(), возможные ответы:

  • ERR_INVALID_PARAMETER (4003)                  – путь к файлу базы содержит пустую строку или выставлена несовместимая комбинация флагов;
  • ERR_NOT_ENOUGH_MEMORY (4004)              - недостаточно памяти;
  • ERR_WRONG_STRING_PARAMETER (5040)      – ошибка конвертации запроса в UTF-8 строку;
  • ERR_DATABASE_INVALID_HANDLE (5121)       - невалидный хендл базы данных;
  • ERR_DATABASE_TOO_MANY_OBJECTS (5122) - превышено максимально допустимое количество объектов Database;
  • ERR_DATABASE_PREPARE (5125)                   - ошибка создания запроса.        

Примечание

Функция DatabasePrepare() не выполняет запрос к базе данных. Её назначение – проверить параметры запроса на корректность и вернуть по результатам данной проверки хендл для выполнения SQL-запроса. Сам запрос будет выполнен при первом вызове DatabaseRead().

Пример:

//--- структура для хранения сделки
struct Deal
  {
   ulong             ticket;           // DEAL_TICKET
   long              order_ticket;     // DEAL_ORDER
   long              position_ticket;  // DEAL_POSITION_ID
   datetime          time;             // DEAL_TIME
   char              type;             // DEAL_TYPE
   char              entry;            // DEAL_ENTRY
   string            symbol;           // DEAL_SYMBOL
   double            volume;           // DEAL_VOLUME
   double            price;            // DEAL_PRICE
   double            profit;           // DEAL_PROFIT
   double            swap;             // DEAL_SWAP
   double            commission;       // DEAL_COMMISSION
   long              magic;            // DEAL_MAGIC
   char              reason;           // DEAL_REASON
  };
//--- структура для хранения трейда - порядок членов соответствует позиции в терминале
struct Trade
  {
   datetime          time_in;          // время входа
   ulong             ticket;           // ID позиции
   char              type;             // покупка или продажа
   double            volume;           // объем
   string            symbol;           // символ
   double            price_in;         // цена входа
   datetime          time_out;         // время выхода
   double            price_out;        // цена выхода
   double            commission;       // комиссия за вход и выход
   double            swap;             // своп
   double            profit;           // прибыль или убыток
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- создадим имя файла
   string filename=IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN))+"_trades.sqlite";
//--- открываем/создаем базу данных в общей папке терминалов
   int db=DatabaseOpen(filenameDATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE | DATABASE_OPEN_COMMON);
   if(db==INVALID_HANDLE)
     {
      Print("DB: "filename" open failed with code "GetLastError());
      return;
     }
//--- создадим таблицу DEALS
   if(!CreateTableDeals(db))
     {
      DatabaseClose(db);
      return;
     }
//---  запросим всю торговую историю
   datetime from_date=0;
   datetime to_date=TimeCurrent();
//--- запросим историю сделок в указанном интервале
   HistorySelect(from_dateto_date);
   int deals_total=HistoryDealsTotal();
   PrintFormat("Торговая история насчитывает сделок: %d "deals_total);
//--- внесем в таблицу сделки
   if(!InsertDeals(db))
      return;
//--- покажем первые 10 сделок
   Deal deals[], deal;
   ArrayResize(deals10);
   int request=DatabasePrepare(db"SELECT * FROM DEALS");
   if(request==INVALID_HANDLE)
     {
      Print("DB: "filename" request failed with code "GetLastError());
      DatabaseClose(db);
      return;
     }
   int i;
   for(i=0DatabaseReadBind(requestdeal); i++)
     {
      if(i>=10)
         break;
      deals[i].ticket=deal.ticket;
      deals[i].order_ticket=deal.order_ticket;
      deals[i].position_ticket=deal.position_ticket;
      deals[i].time=deal.time;
      deals[i].type=deal.type;
      deals[i].entry=deal.entry;
      deals[i].symbol=deal.symbol;
      deals[i].volume=deal.volume;
      deals[i].price=deal.price;
      deals[i].profit=deal.profit;
      deals[i].swap=deal.swap;
      deals[i].commission=deal.commission;
      deals[i].magic=deal.magic;
      deals[i].reason=deal.reason;
     }
//--- выведем сделки на печать
   if(i>0)
     {
      ArrayResize(dealsi);
      PrintFormat("Первые %d сделок:"i);
      ArrayPrint(deals);
     }
//--- delete request after use
   DatabaseFinalize(request);
 
//--- проверим что на счете используется хеджинг для учета открытых позиций
   if((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
     {
      //--- не можем преобразовать сделки в трейды простым способом через транзакции, поэтому завершаем работу
      DatabaseClose(db);
      return;
     }
 
//--- теперь создадим таблицу TRADES на основе таблицы DEALS
   if(!CreateTableTrades(db))
     {
      DatabaseClose(db);
      return;
     }
//--- заполним через SQL-запрос таблицу TRADES на основе данных из DEALS
   ulong start=GetMicrosecondCount();
   if(DatabaseTableExists(db"DEALS"))
      //--- заполним таблицу TRADES
      if(!DatabaseExecute(db"INSERT INTO TRADES(TIME_IN,TICKET,TYPE,VOLUME,SYMBOL,PRICE_IN,TIME_OUT,PRICE_OUT,COMMISSION,SWAP,PROFIT) "
                          "SELECT "
                          "   d1.time as time_in,"
                          "   d1.position_id as ticket,"
                          "   d1.type as type,"
                          "   d1.volume as volume,"
                          "   d1.symbol as symbol,"
                          "   d1.price as price_in,"
                          "   d2.time as time_out,"
                          "   d2.price as price_out,"
                          "   d1.commission+d2.commission as commission,"
                          "   d2.swap as swap,"
                          "   d2.profit as profit "
                          "FROM DEALS d1 "
                          "INNER JOIN DEALS d2 ON d1.position_id=d2.position_id "
                          "WHERE d1.entry=0 AND d2.entry=1"))
        {
         Print("DB: fillng the TRADES table failed with code "GetLastError());
         return;
        }
   ulong transaction_time=GetMicrosecondCount()-start;
   
//--- покажем первые 10 сделок
   Trade trades[], trade;
   ArrayResize(trades10);
   request=DatabasePrepare(db"SELECT * FROM TRADES");
   if(request==INVALID_HANDLE)
     {
      Print("DB: "filename" request failed with code "GetLastError());
      DatabaseClose(db);
      return;
     }
   for(i=0DatabaseReadBind(requesttrade); i++)
     {
      if(i>=10)
         break;
      trades[i].time_in=trade.time_in;
      trades[i].ticket=trade.ticket;
      trades[i].type=trade.type;
      trades[i].volume=trade.volume;
      trades[i].symbol=trade.symbol;
      trades[i].price_in=trade.price_in;
      trades[i].time_out=trade.time_out;
      trades[i].price_out=trade.price_out;
      trades[i].commission=trade.commission;
      trades[i].swap=trade.swap;
      trades[i].profit=trade.profit;
     }
//--- выведем трейды на печать
   if(i>0)
     {
      ArrayResize(tradesi);
      PrintFormat("\r\nПервые %d трейдов:"i);
      ArrayPrint(trades);
      PrintFormat("Заполнение таблицы TRADES заняло %.2f миллисекунд",double(transaction_time)/1000);
     }
//--- удалим запрос после использования
   DatabaseFinalize(request);
 
//--- закрываем базу данных
   DatabaseClose(db);
  }
/*
Результат:
   Торговая история насчитывает сделок: 2741 
   Первые 10 сделок:
       [ticket] [order_ticket] [position_ticket]              [time] [type] [entry] [symbol] [volume]   [price]   [profit] [swap] [commission] [magic] [reason]
   [034429573              0                 0 2019.09.05 22:39:59      2       0 ""        0.00000   0.00000 2000.00000 0.0000      0.00000       0        0
   [134432127       51447238          51447238 2019.09.06 06:00:03      0       0 "USDCAD"  0.10000   1.32320    0.00000 0.0000     -0.16000     500        3
   [234432128       51447239          51447239 2019.09.06 06:00:03      1       0 "USDCHF"  0.10000   0.98697    0.00000 0.0000     -0.16000     500        3
   [334432450       51447565          51447565 2019.09.06 07:00:00      0       0 "EURUSD"  0.10000   1.10348    0.00000 0.0000     -0.18000     400        3
   [434432456       51447571          51447571 2019.09.06 07:00:00      1       0 "AUDUSD"  0.10000   0.68203    0.00000 0.0000     -0.11000     400        3
   [534432879       51448053          51448053 2019.09.06 08:00:00      1       0 "USDCHF"  0.10000   0.98701    0.00000 0.0000     -0.16000     600        3
   [634432888       51448064          51448064 2019.09.06 08:00:00      0       0 "USDJPY"  0.10000 106.96200    0.00000 0.0000     -0.16000     600        3
   [734435147       51450470          51450470 2019.09.06 10:30:00      1       0 "EURUSD"  0.10000   1.10399    0.00000 0.0000     -0.18000     100        3
   [834435152       51450476          51450476 2019.09.06 10:30:00      0       0 "GBPUSD"  0.10000   1.23038    0.00000 0.0000     -0.20000     100        3
   [934435154       51450479          51450479 2019.09.06 10:30:00      1       0 "EURJPY"  0.10000 118.12000    0.00000 0.0000     -0.18000     200        3
 
   Первые 10 трейдов:
                 [time_in] [ticket] [type] [volume] [symbol] [price_in]          [time_out] [price_out] [commission]   [swap]  [profit]
   [02019.09.06 06:00:03 51447238      0  0.10000 "USDCAD"    1.32320 2019.09.06 18:00:00     1.31761     -0.32000  0.00000 -42.43000
   [12019.09.06 06:00:03 51447239      1  0.10000 "USDCHF"    0.98697 2019.09.06 18:00:00     0.98641     -0.32000  0.00000   5.68000
   [22019.09.06 07:00:00 51447565      0  0.10000 "EURUSD"    1.10348 2019.09.09 03:30:00     1.10217     -0.36000 -1.31000 -13.10000
   [32019.09.06 07:00:00 51447571      1  0.10000 "AUDUSD"    0.68203 2019.09.09 03:30:00     0.68419     -0.22000  0.03000 -21.60000
   [42019.09.06 08:00:00 51448053      1  0.10000 "USDCHF"    0.98701 2019.09.06 18:00:01     0.98640     -0.32000  0.00000   6.18000
   [52019.09.06 08:00:00 51448064      0  0.10000 "USDJPY"  106.96200 2019.09.06 18:00:01   106.77000     -0.32000  0.00000 -17.98000
   [62019.09.06 10:30:00 51450470      1  0.10000 "EURUSD"    1.10399 2019.09.06 14:30:00     1.10242     -0.36000  0.00000  15.70000
   [72019.09.06 10:30:00 51450476      0  0.10000 "GBPUSD"    1.23038 2019.09.06 14:30:00     1.23040     -0.40000  0.00000   0.20000
   [82019.09.06 10:30:00 51450479      1  0.10000 "EURJPY"  118.12000 2019.09.06 14:30:00   117.94100     -0.36000  0.00000  16.73000
   [92019.09.06 10:30:00 51450480      0  0.10000 "GBPJPY"  131.65300 2019.09.06 14:30:01   131.62500     -0.40000  0.00000  -2.62000
   Заполнение таблицы TRADES заняло 12.51 milliseconds
*/  
//+------------------------------------------------------------------+
//| Создает таблицу DEALS                                            |
//+------------------------------------------------------------------+
bool CreateTableDeals(int database)
  {
//--- если таблица DEALS уже есть, удалим её
   if(!DeleteTable(database"DEALS"))
     {
      return(false);
     }
//--- проверим наличие таблицы
   if(!DatabaseTableExists(database"DEALS"))
      //--- создаем таблицу
      if(!DatabaseExecute(database"CREATE TABLE DEALS("
                          "ID          INT KEY NOT NULL,"
                          "ORDER_ID    INT     NOT NULL,"
                          "POSITION_ID INT     NOT NULL,"
                          "TIME        INT     NOT NULL,"
                          "TYPE        INT     NOT NULL,"
                          "ENTRY       INT     NOT NULL,"
                          "SYMBOL      CHAR(10),"
                          "VOLUME      REAL,"
                          "PRICE       REAL,"
                          "PROFIT      REAL,"
                          "SWAP        REAL,"
                          "COMMISSION  REAL,"
                          "MAGIC       INT,"
                          "REASON      INT );"))
        {
         Print("DB: create the DEALS table failed with code "GetLastError());
         return(false);
        }
//--- таблица успешно создана
   return(true);
  }
//+------------------------------------------------------------------+
//| Удаляет из базы таблицу с указанным именем                       |
//+------------------------------------------------------------------+
bool DeleteTable(int databasestring table_name)
  {
   if(!DatabaseExecute(database"DROP TABLE IF EXISTS "+table_name))
     {
      Print("Failed to drop the DEALS table with code "GetLastError());
      return(false);
     }
//--- таблица успешно удалена
   return(true);
  }
//+------------------------------------------------------------------+
//| Вносит сделки в таблицу базы данных                              |
//+------------------------------------------------------------------+
bool InsertDeals(int database)
  {
//--- вспомогательные переменные
   ulong    deal_ticket;         // тикет сделки
   long     order_ticket;        // тикет ордера,по которому была совершена сделка
   long     position_ticket;     // ID позиции, к которой относится сделка
   datetime time;                // время совершения сделки
   long     type ;               // тип сделки
   long     entry ;              // направление сделки
   string   symbol;              // по какому символу была сделка
   double   volume;              // объем операции
   double   price;               // цена
   double   profit;              // финансовый результат
   double   swap;                // своп
   double   commission;          // комиссия
   long     magic;               // Magic number (ID советника)
   long     reason;              // причина или источник проведения сделки
//--- пройдем по всем сделкам и внесем их в базу данных
   bool failed=false;
   int deals=HistoryDealsTotal();
//--- заблокируем базу данных перед выполнением транзакций
   DatabaseTransactionBegin(database);
   for(int i=0i<dealsi++)
     {
      deal_ticket=    HistoryDealGetTicket(i);
      order_ticket=   HistoryDealGetInteger(deal_ticketDEAL_ORDER);
      position_ticket=HistoryDealGetInteger(deal_ticketDEAL_POSITION_ID);
      time= (datetime)HistoryDealGetInteger(deal_ticketDEAL_TIME);
      type=           HistoryDealGetInteger(deal_ticketDEAL_TYPE);
      entry=          HistoryDealGetInteger(deal_ticketDEAL_ENTRY);
      symbol=         HistoryDealGetString(deal_ticketDEAL_SYMBOL);
      volume=         HistoryDealGetDouble(deal_ticketDEAL_VOLUME);
      price=          HistoryDealGetDouble(deal_ticketDEAL_PRICE);
      profit=         HistoryDealGetDouble(deal_ticketDEAL_PROFIT);
      swap=           HistoryDealGetDouble(deal_ticketDEAL_SWAP);
      commission=     HistoryDealGetDouble(deal_ticketDEAL_COMMISSION);
      magic=          HistoryDealGetInteger(deal_ticketDEAL_MAGIC);
      reason=         HistoryDealGetInteger(deal_ticketDEAL_REASON);
      //--- внесем в таблицу каждую сделку через запрос
      string request_text=StringFormat("INSERT INTO DEALS (ID,ORDER_ID,POSITION_ID,TIME,TYPE,ENTRY,SYMBOL,VOLUME,PRICE,PROFIT,SWAP,COMMISSION,MAGIC,REASON)"
                                       "VALUES (%d, %d, %d, %d, %d, %d, '%s', %G, %G, %G, %G, %G, %d, %d)",
                                       deal_ticketorder_ticketposition_tickettimetypeentrysymbolvolumepriceprofitswapcommissionmagicreason);
      if(!DatabaseExecute(databaserequest_text))
        {
         PrintFormat("%s: failed to insert deal #%d with code %d"__FUNCTION__deal_ticketGetLastError());
         PrintFormat("i=%d: deal #%d  %s"ideal_ticketsymbol);
         failed=true;
         break;
        }
     }
//--- проверим на наличие ошибок при выполнении транзакций
   if(failed)
     {
      //--- откатим все транзакции и разблокируем базу данных
      DatabaseTransactionRollback(database);
      PrintFormat("%s: DatabaseExecute() failed with code %d"__FUNCTION__GetLastError());
      return(false);
     }
//--- все транзакции прошли успешно - зафиксируем изменения и разблокируем базу данных
   DatabaseTransactionCommit(database);
   return(true);
  }
//+------------------------------------------------------------------+
//| Создает таблицу TRADES                                           |
//+------------------------------------------------------------------+
bool CreateTableTrades(int database)
  {
//--- если таблица TRADES уже есть, удалим её
   if(!DeleteTable(database"TRADES"))
      return(false);
//--- проверим наличие таблицы
   if(!DatabaseTableExists(database"TRADES"))
      //--- создаем таблицу
      if(!DatabaseExecute(database"CREATE TABLE TRADES("
                          "TIME_IN     INT     NOT NULL,"
                          "TICKET      INT     NOT NULL,"
                          "TYPE        INT     NOT NULL,"
                          "VOLUME      REAL,"
                          "SYMBOL      CHAR(10),"
                          "PRICE_IN    REAL,"
                          "TIME_OUT    INT     NOT NULL,"
                          "PRICE_OUT   REAL,"
                          "COMMISSION  REAL,"
                          "SWAP        REAL,"
                          "PROFIT      REAL);"))
        {
         Print("DB: create the TRADES table  failed with code "GetLastError());
         return(false);
        }
//--- таблица успешно создана
   return(true);
  }
//+------------------------------------------------------------------+

Смотри также

DatabaseExecute, DatabaseFinalize