
MQL5'ten (MQL4) MySQL Veritabanına Nasıl Erişilir
Giriş
MQL'nin veritabanları ile etkileşim sorunu yeni değil, ancak yine de alakalıdır. Veritabanlarının kullanımı MetaTrader'ın olanaklarını büyük ölçüde artırabilir: fiyat geçmişinin saklanması ve analizi, alım satımların bir alım satım platformundan diğerine kopyalanması, gerçek zamanlı teklifler/takaslar sağlanması, sunucu tarafında ve/veya bir program kullanılarak yoğun analitik hesaplamalar, web teknolojilerini kullanarak hesapların izlenmesi ve uzaktan kontrolü.
Ayrıca, MQL ve MySQL kombinasyonundan faydalanmak için birçok girişimde bulunuldu; CodeBase'de bazı çözümler mevcut.
Örneğin "MySQL sarmalayıcı - MetaTrader 4 için kitaplık", birçok programcının ek eklemelerle kendi geliştirmelerine başladığı projedir. Bence bu çözümün dezavantajlarından biri, veri tabanından veri okumak için özel dizilerin tahsis edilmesidir.
"MySQL günlükçü+1 - MetaTrader 4 için EA" adlı başka bir proje oldukça uzmanlaşmıştır, libmysql.dll standart kitaplığına erişmek için sarmalayıcı kullanmaz. Bu nedenle MetaTrader4 Build 600+ sürümünde çalışmaz, çünkü char karakter türleri wchar_t ile değiştirilmiştir ve TMYSQL yapı işaretçisi yerine int türünün kullanılması projede bellek sızıntılarına neden olur (tahsis edilen bellek kontrol edilemez/serbest bırakılamaz).
Bir başka ilginç proje ise "EAX_Mysql - MySQL kitaplığı - MetaTrader 5 için kitaplık". Bu oldukça iyi bir uygulamadır. Yazar tarafından belirtilen dezavantajlar listesi, kullanımına bazı kısıtlamalar getirmektedir.
MQL projelerinde veritabanlarını kullanmaya ihtiyaç duyan herkesin iki seçeneği vardır: ya kendi çözümlerini geliştirmek ve her bir parçasını bilmek ya da herhangi bir üçüncü taraf çözümünü kullanmak/uyarlamak, nasıl kullanılacağını öğrenmek ve projelerini engelleyebilecek tüm kusurlarını tespit etmek.
Oldukça karmaşık bir alım satım robotu geliştirirken böyle bir zorunluluk ve iki seçenekle karşılaştım. Mevcut projeleri araştırdıktan ve çok sayıda çözüm üzerinde çalıştıktan sonra, bulunan uygulamaların hiçbirinin alım satım robotumu "profesyonel seviyeye" getirmeye yardımcı olamayacağını fark ettim.
Ayrıca saçma çözümler de vardı, örneğin: DML/DDL işlemleri (veri ekleme/güncelleme/silme, veritabanına nesne oluşturma/bırakma) standart libmysql.dll kullanılarak yapıldı ve veri seçimi (SELECT) aslında MySQL sunucusu tarafında web sunucusunda bulunan bir PHP script dosyasına (inet.dll kullanılarak) bir HTTP isteği olarak uygulandı. SQL sorguları PHP script dosyasına yazılmıştır.
Başka bir deyişle, projeyi çalıştırmak için aşağıdaki bileşenlerin kullanılabilir, yapılandırılmış ve çalışır durumda tutulması gerekiyordu: MySQL sunucusu, Apache/IIS web sunucusu, sunucu tarafında PHP/ASP script dosyaları... Oldukça fazla sayıda teknolojinin bir kombinasyonu. Elbette, bazı durumlarda bu kabul edilebilir, ancak tek görev veri tabanından veri seçmek olduğunda bu saçmalıktır. Ek olarak, böyle hantal bir çözümü desteklemek zaman alıcıdır.
Çözümlerin çoğunda veri ekleme, nesne oluşturma ve benzerlerinde sorun yoktu. Sorun, verilerin çağrı ortamına döndürülmesi gerektiği için veri seçimiydi.
Dizileri bu amaç için kullanmanın pratik ve elverişsiz olduğunu düşündüm, çünkü ana projenin geliştirilmesi/hata ayıklaması/desteklenmesi sırasında, veritabanına yönelik seçme sorguları değiştirilebilirken, diziler için doğru bellek tahsisini de kontrol etmelisiniz. Yani, bu kaçınılabilir ve kaçınılmalıdır.
Aşağıda tartışılan MQL <-> MySql arabirimi, Oracle PL/SQL, MS SQL T-SQL, AdoDB imleçlerin kullanımında kullanılan tipik bir yaklaşıma dayanmaktadır. Bu arayüz, programlama ve bakım kolaylığı ile minimum bileşen hedeflenerek geliştirilmiştir. Standart libmysql.dll kitaplığına bir DLL sarmalayıcısı olarak uygulanır ve bir .mqh dosyası olarak bir dizi arabirim işlevi vardır.
1. MQL <-> MySQL Arayüzü
MetaTrader terminali (MQL programları aracılığıyla) arasındaki etkileşim, aşağıdaki bileşenlerin yardımıyla uygulanabilir:
1. Arabirim kitaplığı MQLMySQL.mqh. #include dizini kullanılarak projeye eklenir ve zevkinize göre değiştirilebilir.
MQLMySQL.dll dinamik kitaplığının içe aktarma işlevlerinin yanı sıra bunları çağırma ve hataları işleme işlevleri için yönergeleri içerir.
2. MQLMySQL.dll dinamik kitaplığı. Standart kitaplık libmysql.dll'nin işlevselliğine erişmek için bir sarmalayıcıdır.
Ayrıca, MQLMySQL.dll kitaplığı, işlemlerin sonuçlarını ve veritabanı bağlantılarına ve imleçlere paylaşılan erişimi işler. Bu, aynı anda birden çok bağlantı oluşturup kullanabileceğiniz (bir veya daha fazla MQL programından), bir veya daha fazla veritabanına sorgularla birlikte birkaç imleci açık tutabileceğiniz anlamına gelir. Muteksler, paylaşılan kaynaklara erişimi ayırmak için kullanılır.
3. Standart dinamik kitaplık libmysql.dll, yerel bir erişim sürücüsüdür. C:\Windows\System32 veya <Terminal>\MQL5\Libraries içindeki herhangi bir MySql veritabanı dağıtımından kopyalayabilirsiniz (<Terminal>\MQL4\Libraries içinde MetaTrader 4 için).
Aslında, veritabanına sorgular göndermekten ve sonuçları almaktan sorumludur.
Bağlantının açılması/kapatılması, DML/DDL sorgularının yapılması ve veri seçimi gibi ana noktalar üzerinde duralım.
1.1. Bağlantıyı Açma ve Kapatma
MySqlConnect işlevi, MySQL veritabanıyla bağlantı açmak için uygulandı:
Tür | Ad | Parametreler | Açıklama |
int | MySqlConnect | Bu işlev, veritabanıyla bağlantı kurar ve bir bağlantı tanımlayıcısı döndürür. Bu kimlik, veritabanını sorgulamak için gerekli olacaktır. Bağlantı hatası durumunda dönüş değeri "-1"dir. Hata ayrıntıları için MySQLErrorNumber ve MySqlErrorDescription değişkenlerini kontrol edin. Genellikle bu işlev, MQL programında OnInit() olayı işlenirken çağrılır. | |
dize pHost | MySQL sunucusunun DNS adı veya IP adresi | ||
dize pUser | Veritabanı kullanıcısı (örneğin kök) | ||
dize pPassword | Veritabanı kullanıcısının parolası | ||
dize pDatabase | Veritabanının adı | ||
int pPort | Veritabanının TCP/IP bağlantı noktası (genellikle 3306) | ||
dize pSocket | Unix soketi (Unix tabanlı sistemler için) | ||
int pClientFlag | Özel bayrakların kombinasyonu (genellikle 0) |
Bağlantıyı kapatmak için MySqlDisconnect arabirim işlevi uygulanmıştır:
Tür | Adı | Parametreler | Açıklama |
boş | MySqlDisconnect | Bu fonksiyon MySQL veritabanı ile bağlantıyı kapatır. Genellikle bu işlev, MQL programında OnDeinit() olayı işlenirken çağrılır. | |
int pConnection | Bağlantı tanımlayıcı |
Unutulmamalıdır ki, bir donanım arızası, ağ tıkanıklığı veya zaman aşımı (veritabanına uzun süre sorgu gönderilmediğinde) durumunda MySQL veritabanı bağlantıyı kendiliğinden kapatabilir.
Geliştiriciler genellikle veritabanına veri yazmak için OnTick() olayını kullanır. Ancak, hafta sonu geldiğinde ve piyasa kapandığında, bağlantı hala "devam eder". Bu durumda MySQL, zaman aşımına uğradığında kapanır (varsayılan 8 saattir).
Pazartesi günü piyasa açıkken projede hatalar bulunur. Bu nedenle, MySQL sunucusunun ayarlarında belirtilen zaman aşımı süresinden daha küçük bir zaman aralığından sonra bağlantıyı kontrol etmeniz ve/veya veritabanına yeniden bağlanmanız şiddetle tavsiye edilir.
1.2. DML/DDL Sorgularının Yürütülmesi
DML işlemleri veri manipülasyonları için kullanılır (Data Manipulation Language). Veri manipülasyonları aşağıdaki ifadeleri içerir: EKLE, GÜNCLLE ve SİL.
DDL işlemleri veri tanımlaması için kullanılır (Data Definition Language). Bu, veritabanı nesnelerinin (tablolar, görünümler, saklı yordamlar, tetikleyiciler vb.) oluşturulmasını (CREATE) ve bunların değiştirilmesini (ALTER) ve silinmesini (DROP) içerir.
Bunların hepsi DML/DDL deyimleri değildir, ayrıca DCL (Data Control Language) veri erişimini ayırmak için kullanılır, ancak SQL'in özelliklerini ayrıntılı olarak incelemeyeceğiz. Bu komutlardan herhangi biri MySqlExecute arayüz işlevi kullanılarak yürütülebilir:
Tür | Ad | Parametreler | Açıklama |
bool | MySqlExecute | Bu işlev, veritabanına bağlantı başarıyla kurulduktan sonra (MySqlConnect işlevini kullanarak) SQL'in SELECT olmayan deyimlerini yürütmek için kullanılabilir. Komutun başarılı bir şekilde yürütülmesi durumunda işlev doğru, aksi takdirde yanlış döndürür. Hata ayrıntıları için MySQLErrorNumber ve MySqlErrorDescription kullanın. | |
int pConnection | Bağlantı tanımlayıcı | ||
dize pQuery | SQL Sorgusu |
SQL sorgusu olarak, veritabanını seçmek için USE komutunu da kullanabilirsiniz. Çok ifadeli sorguların kullanımından bahsetmek istiyorum. ";" karakteriyle ayrılmış bir dizi SQL komutudur.
Çoklu ifade modunu etkinleştirmek için, veritabanı ile bağlantı CLIENT_MULTI_STATEMENTS bayrağı ile açılmalıdır:
... int ClientFlag = CLIENT_MULTI_STATEMENTS; // Setting the multi-statements flag int DB; DB = MySqlConnect(Host, User, Password, Database, Port, Socket, ClientFlag); // Connection to the database if (DB == -1) { // Handling the connection error } ... // Preparing a SQL query to insert data (3 rows in one query) string SQL; SQL = "INSERT INTO EURUSD(Ask,Bid) VALUES (1.3601,1.3632);"; SQL = SQL + "INSERT INTO EURUSD(Ask,Bid) VALUES (1.3621,1.3643);"; SQL = SQL + "INSERT INTO EURUSD(Ask,Bid) VALUES (1.3605,1.3629);"; ... if (!MySqlExecute(DB,SQL)) { // Showing an error message } ...
Bu parçada, veritabanına yapılan tek bir çağrı ile EURUSD tablosuna 3 giriş eklenecektir. SQL değişkeninde depolanan sorguların her biri ";" ile ayrılır.
Bu yaklaşım, sık ekleme/güncelleme/silme için kullanılabilir; bir dizi gerekli komut tek bir "paket" içinde birleştirilir, böylece ağ trafiği rahatlatılır ve veritabanı performansı iyileştirilir.
MySQL'deki INSERT sözdizimi, istisna işleme açısından oldukça iyi geliştirilmiştir.
Örneğin görev fiyat geçmişini taşımaksa bir çubuğun tarih ve saati benzersiz olduğundan, tarih saat türünün birincil anahtarı ile döviz çiftleri için bir tablo oluşturulmalıdır. Ayrıca herhangi bir çubuktaki verilerin veritabanında olup olmadığı kontrol edilmelidir (veri geçişinin kararlılığını artırmak için). MySQL ile bu kontrol gerekli değildir, çünkü INSERT ifadesi ON DUPLICATE KEY'i destekler.
Daha basit bir deyişle, veri ekleme girişiminde bulunulursa ve tablo aynı tarih ve saate sahip bir girişe sahipse INSERT ifadesi yok sayılabilir veya bu satır için UPDATE ile değiştirilebilir (bkz. http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html)
1.3. Veri Seçimi
SQL SELECT ifadesi, veritabanından veri almak için kullanılır. Aşağıdaki işlem sırası, verileri seçmek ve seçim sonucunu almak için kullanılır:
- SELECT ifadesinin hazırlanması.
- İmleci açma.
- Sorgu tarafından döndürülen satır sayısını alma.
- Sorgunun her satırını döngüleme ve alma.
- Döngü içindeki MQL değişkenlerine veri getirme.
- İmleci kapatma.
Elbette bu genel bir şemadır, bu nedenle her durum için tüm işlemler gerekli değildir. Örneğin tabloda bir satırın (herhangi bir kritere göre) olduğundan emin olmak istiyorsanız bir sorgu hazırlamanız, bir imleç açmanız, satır sayısını almanız ve imleci kapatmanız yeterli olacaktır. Aslında, zorunlu kısımlar SELECT ifadesini hazırlamak, imleci açmak ve kapatmaktır.
İmleç nedir? Bu bağlam bellek alanına bir referanstır; aslında sonuçta ortaya çıkan değerler kümesidir. SELECT sorgusunu gönderdiğinizde, veritabanı sonuç için bellek ayırır ve bir satırdan diğerine taşıyabileceğiniz bir satıra bir işaretçi oluşturur. Böylece, sorgu tarafından tanımlanan bir sıradaki tüm satırlara (SELECT ifadesinin ORDER BY yan tümcesi) erişmek mümkündür.
Veri seçimi için aşağıdaki arayüz işlevleri kullanılır:
İmleci açma:
Tür | Ad | Parametreler | Açıklama |
int | MySqlCursorOpen | Bu işlev, SELECT sorgusu için bir imleç açar ve başarılı olması durumunda bir imleç tanımlayıcısı döndürür. Aksi takdirde, işlev "-1" döndürür. Hatanın nedenini bulmak için MySQLErrorNumber ve MySqlErrorDescription değişkenlerini kullanın. | |
int pConnection | Veritabanı ile bağlantı tanımlayıcısı | ||
dize pQuery | SQL sorgusu (SELECT ifadesi) |
Sorgu tarafından döndürülen satır sayısını alma:
Tür | Ad | Parametreler | Açıklama |
int | MySqlCursorRows | Bu işlev, sorgu tarafından seçilen satır sayısını döndürür. | |
int pCursorID | MySqlCursorOpen tarafından döndürülen imleç tanımlayıcısı |
Sorgu satırı getiriliyor:
Tür | Ad | Parametreler | Açıklama |
bool | MySqlCursorFetchRow | Sorgu tarafından döndürülen veri kümesinden bir satır getirir. Başarılı yürütmeden sonra verileri MQL değişkenlerine alabilirsiniz. İşlev başarılıysa doğru, aksi takdirde yanlış döndürür. | |
int pCursorID | MySqlCursorOpen tarafından döndürülen imleç tanımlayıcısı |
Sorgu satırını getirdikten sonra verileri MQL değişkenlerine getirme:
Tür | Ad | Parametreler | Açıklama |
int | MySqlGetFieldAsInt | Bu işlev, int veri türünü kullanarak tablo alanı değerinin temsilini döndürür. | |
int pCursorID | MySqlCursorOpen tarafından döndürülen imleç tanımlayıcısı | ||
int pField | SEÇ listesindeki alan numarası (numaralandırma 0 ile başlar) | ||
double | MySqlGetFieldAsDouble | Bu işlev, çift veri türünü kullanarak tablo alanı değerinin temsilini döndürür. | |
int pCursorID | MySqlCursorOpen tarafından döndürülen imleç tanımlayıcısı | ||
int pField | SEÇ listesindeki alan numarası (numaralandırma 0 ile başlar) | ||
tarihsaat | MySqlGetFieldAsDatetime | Bu işlev, tarih saat veri türünü kullanarak tablo alanı değerinin temsilini döndürür. | |
int pCursorID | MySqlCursorOpen tarafından döndürülen imleç tanımlayıcısı | ||
int pField | SEÇ listesindeki alan numarası (numaralandırma 0 ile başlar) | ||
dize | MySqlGetFieldAsString | Bu işlev, dize veri türünü kullanarak tablo alanı değerinin temsilini döndürür. | |
int pCursorID | MySqlCursorOpen tarafından döndürülen imleç tanımlayıcısı | ||
int pField | SEÇ listesindeki alan numarası (numaralandırma 0 ile başlar) |
MySQL tarafından döndürülen tüm veriler yerel temsile sahiptir (türler olmadan dizeler olarak sunulur).
Bu nedenle, bu işlevleri kullanarak seçilen verileri istediğiniz türe çevirebilirsiniz. Tek dezavantajı, SELECT listesinde adı yerine sütun numarasının (numaralandırma 0'dan başlar) belirtilmesidir. Ancak bir uygulama geliştirirken, SELECT ifadesinin hazırlanması ve sonuçların alınması neredeyse her zaman bir sayfadadır; bu nedenle veri getirme mantığını yazarken SELECT sorgusunu görebilirsiniz.
Böylece SELECT listesindeki alanların numaralarını her zaman bilirsiniz (bu yaklaşım, AdoDB kullanılarak verilere erişilirken de kullanılır). Ayrıca, bu kısım gelecekte daha da revize edilebilir. Ancak bunun geliştirilen çözümün işlevselliği üzerinde çok az etkisi olacaktır.
İmleci kapatma:
Tür | Ad | Parametreler | Açıklama |
boş | MySqlCursorClose | Bu işlev belirtilen imleci kapatır ve belleği serbest bırakır. | |
int pCursorID | MySqlCursorOpen tarafından döndürülen imleç tanımlayıcısı |
Bir imleci kapatmak kritik bir işlemdir. İmleçleri kapatmayı unutmayın.
İmleci açtığınızı ve kapatmayı unuttuğunuzu hayal edin. OnTick() olayı işlenirken her onay işareti ile imlece veri alındığını ve her yeni imleç açıldığında, bunun için bellek ayrıldığını (hem istemci tarafında hem de sunucu tarafında) varsayalım. Bir noktada, sunucu, açık imleç sınırına ulaşıldığından hizmeti reddeder ve bu, arabellek taşmasına neden olabilir.
Elbette bu abartılıdır; böyle bir sonuç libmysql.dll ile doğrudan çalışırken mümkündür. Ancak, MQLMySQL.DLL dinamik kitaplığı imleçler için belleği dağıtır ve izin verilen sınırı aşan bir imleci açmayı reddeder.
Gerçek görevleri uygularken 2-3 imleci açık tutmak yeterlidir. Her imleç bir Kartezyen veri ölçümünü işleyebilir; aynı anda iki-üç imleç kullanmak (örneğin biri parametrik olarak başka bir imlece bağlı olduğunda iç içe geçmiş) iki veya üç boyutu kapsar. Bu, çoğu görev için oldukça iyidir. Ayrıca, karmaşık veri seçiminin uygulanmasında, bu nesneleri her zaman veritabanını temsil etmek (VIEW) için kullanabilir, bunları sunucu tarafında oluşturabilir ve MQL kodundan tablolara sorgular gönderebilirsiniz.
1.4. Ek Bilgiler
Ek özellikler olarak şunlardan bahsedilebilir:
1.4.1. Bir .INI dosyasından veri okuma
Tür | Ad | Parametreler | Açıklama |
Dize | ReadIni | INI dosyasının verilen bölümünün bir anahtarının değerini döndürür. | |
dize pDosyaAdı | INI dosyasının adı | ||
dize pSection | Bölüm adı | ||
dize pKey | Anahtar adı |
Genellikle veritabanına bağlantılar hakkında bilgileri (sunucunun IP adresi, bağlantı noktası, kullanıcı adı, şifre vb.) doğrudan MQL kodunda (veya Expert Advisor'ın parametreleri, komut dosyası göstergesi) depolamak mantıklı değildir, çünkü sunucu taşındı, adresi dinamik olarak değişebilir vb. Bu durumda MQL kodunu değiştirmeniz gerekecektir. Bu nedenle, tüm bu veriler standart .INI dosyasında saklanmalı, MQL programında sadece adı yazılmalıdır. Ardından, bağlantı parametrelerini okumak ve bunları kullanmak için ReadINI işlevini kullanın.
Örneğin INI dosyası aşağıdaki bilgileri içerir:
[MYSQL] Server = 127.0.0.1 User = root Password = Adm1n1str@t0r Database = mysql Port = 3306
Sunucunun IP adresini almak için aşağıdakileri yürütün:
string vServer = ReadIni("C:\\MetaTrader5\\MQL5\\Experts\\MyConnection.ini", "MYSQL", "Server");
INI dosyası C:\MetaTrader5\MQL5\Experts konumunda bulunur ve "MyConnection.ini" olarak adlandırılır, MYSQL bölümünün Sunucu anahtarına erişirsiniz. Bir INI dosyasında, projenizde kullanılan çeşitli sunuculara ait ayarları saklayabilirsiniz.
1.4.2. Sorunlu Alanları İzleme
Arabirim kitaplığında, bir MQL programında herhangi bir yerde SQL sorgularında hata ayıklamak için etkinleştirilebilen izleme modu bulunur.
Sorun alanında şunları belirtin:
SQLTrace = true;
ve ardından
SQLTrace = false;
MQL programının başlangıcında izlemeyi etkinleştirir ve devre dışı bırakmazsanız veritabanına yapılan tüm çağrılar günlüğe kaydedilir. Günlük, terminal konsolunda tutulur (Yazdır komutu kullanılarak).
2. Örnekler
Bu bölüm, geliştirilen kitaplıkların bağlantı ve kullanımına ilişkin birkaç örnek sunmaktadır. Bunları görün ve yazılım çözümünün kullanılabilirliğini tahmin edin.
MySQL-003.mq5 örneği şunları gösterir: bir veritabanına bağlanma (bağlantı parametreleri .ini dosyasında saklanır), bir tablo oluşturma, veri ekleme (ayrıca çoklu ifadeler) ve veritabanından bağlantının kesilmesi.
//+------------------------------------------------------------------+ //| MySQL-003.mq5 | //| Copyright 2014, Eugene Lugovoy | //| https://www.mql5.com | //| Inserting data with multi-statement (DEMO) | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, Eugene Lugovoy." #property link "https://www.mql5.com" #property version "1.00" #property strict #include <MQLMySQL.mqh> string INI; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { string Host, User, Password, Database, Socket; // database credentials int Port,ClientFlag; int DB; // database identifier Print (MySqlVersion()); INI = TerminalInfoString(TERMINAL_PATH)+"\\MQL5\\Scripts\\MyConnection.ini"; // reading database credentials from INI file Host = ReadIni(INI, "MYSQL", "Host"); User = ReadIni(INI, "MYSQL", "User"); Password = ReadIni(INI, "MYSQL", "Password"); Database = ReadIni(INI, "MYSQL", "Database"); Port = (int)StringToInteger(ReadIni(INI, "MYSQL", "Port")); Socket = ReadIni(INI, "MYSQL", "Socket"); ClientFlag = CLIENT_MULTI_STATEMENTS; //(int)StringToInteger(ReadIni(INI, "MYSQL", "ClientFlag")); Print ("Host: ",Host, ", User: ", User, ", Database: ",Database); // open database connection Print ("Connecting..."); DB = MySqlConnect(Host, User, Password, Database, Port, Socket, ClientFlag); if (DB == -1) { Print ("Connection failed! Error: "+MySqlErrorDescription); } else { Print ("Connected! DBID#",DB);} string Query; Query = "DROP TABLE IF EXISTS `test_table`"; MySqlExecute(DB, Query); Query = "CREATE TABLE `test_table` (id int, code varchar(50), start_date datetime)"; if (MySqlExecute(DB, Query)) { Print ("Table `test_table` created."); // Inserting data 1 row Query = "INSERT INTO `test_table` (id, code, start_date) VALUES ("+(string)AccountInfoInteger(ACCOUNT_LOGIN)+",\'ACCOUNT\',\'"+TimeToString(TimeLocal(), TIME_DATE|TIME_SECONDS)+"\')"; if (MySqlExecute(DB, Query)) { Print ("Succeeded: ", Query); } else { Print ("Error: ", MySqlErrorDescription); Print ("Query: ", Query); } // multi-insert Query = "INSERT INTO `test_table` (id, code, start_date) VALUES (1,\'EURUSD\',\'2014.01.01 00:00:01\');"; Query = Query + "INSERT INTO `test_table` (id, code, start_date) VALUES (2,\'EURJPY\',\'2014.01.02 00:02:00\');"; Query = Query + "INSERT INTO `test_table` (id, code, start_date) VALUES (3,\'USDJPY\',\'2014.01.03 03:00:00\');"; if (MySqlExecute(DB, Query)) { Print ("Succeeded! 3 rows has been inserted by one query."); } else { Print ("Error of multiple statements: ", MySqlErrorDescription); } } else { Print ("Table `test_table` cannot be created. Error: ", MySqlErrorDescription); } MySqlDisconnect(DB); Print ("Disconnected. Script done!"); }
Örnek MySQL-004.mq5 "MySQL-003.mq5" komut dosyası tarafından oluşturulan bir tablodan veri seçimini gösterir.
//+------------------------------------------------------------------+ //| MySQL-004.mq5 | //| Copyright 2014, Eugene Lugovoy | //| https://www.mql5.com | //| Select data from table (DEMO) | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, Eugene Lugovoy." #property link "https://www.mql5.com" #property version "1.00" #property strict #include <MQLMySQL.mqh> string INI; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { string Host, User, Password, Database, Socket; // database credentials int Port,ClientFlag; int DB; // database identifier Print (MySqlVersion()); INI = TerminalInfoString(TERMINAL_PATH)+"\\MQL5\\Scripts\\MyConnection.ini"; // reading database credentials from INI file Host = ReadIni(INI, "MYSQL", "Host"); User = ReadIni(INI, "MYSQL", "User"); Password = ReadIni(INI, "MYSQL", "Password"); Database = ReadIni(INI, "MYSQL", "Database"); Port = (int)StringToInteger(ReadIni(INI, "MYSQL", "Port")); Socket = ReadIni(INI, "MYSQL", "Socket"); ClientFlag = (int)StringToInteger(ReadIni(INI, "MYSQL", "ClientFlag")); Print ("Host: ",Host, ", User: ", User, ", Database: ",Database); // open database connection Print ("Connecting..."); DB = MySqlConnect(Host, User, Password, Database, Port, Socket, ClientFlag); if (DB == -1) { Print ("Connection failed! Error: "+MySqlErrorDescription); return; } else { Print ("Connected! DBID#",DB);} // executing SELECT statement string Query; int i,Cursor,Rows; int vId; string vCode; datetime vStartTime; Query = "SELECT id, code, start_date FROM `test_table`"; Print ("SQL> ", Query); Cursor = MySqlCursorOpen(DB, Query); if (Cursor >= 0) { Rows = MySqlCursorRows(Cursor); Print (Rows, " row(s) selected."); for (i=0; i<Rows; i++) if (MySqlCursorFetchRow(Cursor)) { vId = MySqlGetFieldAsInt(Cursor, 0); // id vCode = MySqlGetFieldAsString(Cursor, 1); // code vStartTime = MySqlGetFieldAsDatetime(Cursor, 2); // start_time Print ("ROW[",i,"]: id = ", vId, ", code = ", vCode, ", start_time = ", TimeToString(vStartTime, TIME_DATE|TIME_SECONDS)); } MySqlCursorClose(Cursor); // NEVER FORGET TO CLOSE CURSOR !!! } else { Print ("Cursor opening failed. Error: ", MySqlErrorDescription); } MySqlDisconnect(DB); Print ("Disconnected. Script done!"); }
Yukarıdaki örnekler, gerçek projelerde kullanılan tipik hata işlemeyi içerir.
Aslında, bir MQL programında kullanılan her sorgu, herhangi bir MySQL istemcisinde (PHPMyAdmin, DB Ninja, MySQL konsolu) hata ayıklanmalıdır. Şahsen veritabanı geliştirme için profesyonel yazılımlar kullanıyorum ve MySQL için Quest TOAD yazılımını tavsiye ediyorum.
Sonuç
Bu makale, Microsoft Visual Studio 2010 (C/C++) ortamında geliştirilen MQLMySQL.DLL uygulamasının ayrıntılarını açıklamamaktadır. Bu yazılım çözümü pratik kullanım için tasarlanmıştır ve MQL yazılım geliştirmenin çeşitli alanlarında (karmaşık alım satım sistemlerinin oluşturulmasından web yayıncılığına kadar) 100'den fazla başarılı uygulamaya sahiptir.
- MQL4 ve MQL5 kitaplıklarının sürümleri aşağıda eklenmiştir. Ekler ayrıca MQLMySQL.DLL kaynak kodunu içeren bir zip dosyası içerir;
- Dokümantasyon arşivlerde yer almaktadır;
- Örnekleri kullanmak için, \Scripts\MyConnection.ini dosyasında veritabanınıza bağlantı parametrelerini belirtmeyi unutmayın.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/932





- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz