MQL5 中的数据库操作原理
数据库以表的形式存储信息。获取、修改和向其中添加新数据都是使用 SQL 语言查询完成的。我们将在以下章节中描述其具体细节。与此同时,我们借助与交易无关的 DatabaseRead.mq5 脚本,了解如何创建一个简单的数据库并从中获取信息。这里提到的所有函数稍后都会详细描述。现在一定要想象一下总体原则。
使用内置的 DatabaseOpen/DatabaseClose 函数创建和关闭数据库,类似于处理文件,因为我们也为数据库创建一个描述符,检查数据库,并在最后将其关闭。
void OnStart()
|
打开数据库后,我们将确保其中没有以我们所需名称命名的表。如果表已存在,那么当尝试像我们的示例中那样向其插入相同数据时,将会发生错误,因此我们使用 DatabaseTableExists 函数。
删除和创建表是通过查询完成的,这些查询通过两次调用 DatabaseExecute 函数发送到数据库,并伴有错误检查。
...
|
我们来阐述一下 SQL 查询的本质。在 COMPANY 表中,我们只有 5 个字段:记录 ID、姓名、年龄、地址和薪水。这里的 ID 字段是一个键,即唯一索引。索引能够唯一标识每条记录,并可跨表用于将它们链接在一起。这类似于仓位 ID 链接属于特定仓位的所有交易和订单。
现在你需要用数据填充表,这是通过 "INSERT" 查询完成的:
// insert data into table
|
在这里,向 COMPANY 表添加了 4 条记录,每条记录都有一个字段列表,并指明了将写入这些字段的值。记录是通过单独的 "INSERT..." 查询插入的,这些查询通过特殊的分隔符 ';' 组合成一行,但我们也可以通过单独的 DatabaseExecute 调用将每条记录插入表中。
由于脚本末尾数据库将保存到 "company.sqlite" 文件中,下次运行时,我们会尝试使用相同的 ID 将相同的数据写入 COMPANY 表。这将导致出现错误,因此我们之前删除了表,以便每次运行脚本时都从头开始。
现在,我们从 COMPANY 表中获取 SALARY > 15000 字段的所有记录。这是通过 DatabasePrepare 函数完成的,该函数会“编译”请求文本并返回其句柄,以供后续在 DatabaseRead 或 DatabaseReadBind 函数的字符串参数传递给 SQLite 执行引擎。
// prepare a request with a descriptor
|
成功创建请求后,我们需要获取其执行结果。这可以使用 DatabaseRead 函数完成,该函数在第一次调用时将执行查询并跳转到结果中的第一条记录。在每次后续调用时,它将读取下一条记录,直到到达末尾。在这种情况下,它将返回 false,表示“没有更多记录了”。
// printing all records with salary over 15000
|
执行结果将是:
Persons with salary > 15000:
|
DatabaseRead 函数允许遍历查询结果中的所有记录,然后通过 DatabaseColumn 函数获取结果表中每一列的完整信息。这些函数旨在以通用方式处理任何查询的结果,但代价是代码冗余。
如果预先知道查询结果的结构,最好使用 DatabaseReadBind 函数,它允许一次将整个记录读入一个结构体中。我们可以用这种方式重制前面的示例,并以新名称 DatabaseReadBind.mq5 呈现它。首先,我们声明 Person 结构体:
struct Person
|
然后,只要函数返回 true,我们就在循环中用 DatabaseReadBind(request, person) 从查询结果中减去(读取)每条记录:
Person person;
|
因此,我们立即从当前记录中获取所有字段的值,而无需单独读取它们。
这个入门示例摘录自文章 SQLite:在 MQL5 中本地处理 SQL 数据库,其中除了这个示例外,还考虑了交易者应用数据库的几种方案。具体来说,你可以在那里找到从交易中恢复仓位历史、从策略、交易品种或最优选交易时段等方面分析交易报告,以及处理优化结果的技术。
掌握这些材料可能需要一些 SQL 基础知识,因此我们将在后续章节中简要介绍。