将数据绑定到查询参数:DatabaseBind/Array

在 SQL 查询已通过 DatabasePrepare 函数编译后,你可以使用接收到的查询句柄将数据绑定到查询参数,这正是 DatabaseBindDatabaseBindArray 函数的用途。这两个函数不仅可以在 DatabasePrepare 中创建查询后立即调用,也可以在通过 DatabaseReset 将请求重置到其初始状态后调用(如果请求在循环中多次执行)。

数据绑定步骤并非总是必需的,因为预置查询可能没有参数。一般来说,如果查询从 SQL 向 MQL5 返回数据,并因此需要查询描述符,便会发生这种情况:如何通过其句柄读取查询结果在关于 DatabaseRead/DatabaseReadBindDatabaseColumn函数的章节中介绍

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" 替换,则需要调用索引为 9 的 DatabaseBind

DatabaseBind 原型中的 value 可以是任何 简单类型 或字符串。如果参数需要映射复合类型数据(结构体)或可以表示为字节数组的任意二进制数据,请使用 DatabaseBindArray 函数。

函数成功时返回 true。否则,返回 false

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

DatabaseBindArray 函数为具有 request 句柄的查询,将 index 参数的值设置为一个简单类型或简单结构体(包括字符串)的数组。此函数可用于向数据库写入 BLOB 和 NULL(表示缺少值,在 SQL 中被认为是单独类型且不等于 0)。

现在,我们回到 DBSQLite.mqh 文件中的 DBQuery 类,并添加数据绑定支持。

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 函数将其读入字节数组。

显式绑定空值的必要性不那么明显。向数据库插入新记录时,调用程序通常只传递其已知的字段,而所有缺失的字段(如果它们没有用 NOT NULL 约束标记,或者在表描述中没有不同的 DEFAULT 值)将由引擎自动保留为 NULL。然而,在使用 ORM 方法时,将整个对象写入数据库很方便,包括带有唯一主键 (PRIMARY KEY) 的字段。新对象尚不具有此标识符,因为数据库本身在首次写入对象时会添加它,因此将新对象中的此字段绑定到 NULL 值非常重要。