DEBUG.WIKI
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
雨云;给项目一台云服务器
晚安云;香港 CN2 ¥15/月

MySqlConnector 发送 NULL 却报 Incorrect arguments to mysqld_stmt_execute

MySqlConnector 2.5.0 以后把 DbType.Object 优先映射成 Vector,可能让 MySQL 8.4 拒绝预处理语句中的 NULL 参数。按参数真实含义显式指定 Null 或列类型,不能靠去掉 Prepare 认定已修。

向 MySQL 8.4 的可空列写入 DBNull.Value,参数也确实是 NULL,执行却报:

MySqlException: Incorrect arguments to mysqld_stmt_execute

若使用 MySqlConnector 2.5.0 至 2.6.2,并且通用数据访问层把该参数设置成 DbType.Object,应检查它最终对应的 MySqlDbType。在这条映射路径中,Object 会变成 Vector;MySQL 8.4 不支持该类型,预处理执行因此可能失败。

NULL 值与发送的类型是两项信息

2.6.2 的类型表先登记 ReadOnlyMemory<float> 的 VECTOR 映射,它使用 DbType.Object;随后才登记 object 的 NULL 映射。按 DbType 查找时取第一个匹配项,于是显式设置 Object 会得到 Vector。

值为 DBNull.Value 不会取消已经显式设置的参数类型。看到 Value 是 NULL,就认定发送类型也一定是 Null,会漏掉这条分支。可以在受控诊断中查看参数名称、DbType、MySqlDbType 和是否为 DBNull;不需要打印参数真实内容。

这里说的是 MySqlConnector 包,不是另一个提供程序 MySql.Data。还应确认实际服务器版本、连接和命令是否走预处理。错误文本本身也可能由其他参数协议问题引起,不能仅凭一句错误就统一改类型。

已确认只有 NULL 的参数,显式使用 Null

以下是已有命令的参数片段,命令 SQL 中已声明 @v:

using MySqlConnector;

var parameter = new MySqlParameter("@v", MySqlDbType.Null)
{
    Value = DBNull.Value
};
command.Parameters.Add(parameter);

它避开通用 DbType.Object 的反向查找,同时保留 SQL NULL,不把空字符串、零或空字节数组当成替代值。调用方原有的事务、命令生命周期和其他参数应保持不变。

如果同一个参数稍后还会发送非空值,更适合按该列的实际类型建立参数,并在空值时只设置 Value = DBNull.Value。例如真实 VARCHAR 列可使用 VarChar;数值、二进制或 GEOMETRY 列则应保留各自的类型,不能一律改成字符串。列映射由 ORM 或公共参数工厂负责时,需要改那个实际生成参数的入口,单独补一条不被调用的 ADO.NET 代码没有作用。

真正发送向量的应用仍需匹配支持 VECTOR 的服务器和对应值类型。不能把所有 DbType.Object 都强制改成 Null,导致原本的非空对象或向量失去正确契约。

去掉 Prepare 不足以验证恢复

同一连接上,某段 SQL 一旦已经准备过,后面用相同文本新建命令,即使不显式调用 Prepare,也可能继续命中已准备语句。因此,“删掉这一行后仍失败”并不能排除参数类型问题;反过来,用另一条未准备语句成功,也不能证明原入口恢复。

在隔离测试表或获准的事务范围内,分别检查 NULL 与非空值、明确 Prepare 的调用,以及同一连接复用原 SQL 的路径。断言写入和读回仍为 NULL,并核对非空值没有被转换或截断。不要在执行结果不明时自动重放写入;按应用原有事务策略确认本次是否已经提交。

截至 2026 年 10 月 24 日,正式 2.6.2 仍有上述映射顺序。更换驱动版本时,应核对正式实现及这组参数回归,不能仅凭一个待合并的映射调整认定运行依赖已修复。