如何在C ++中使用SQLGetData将MySQL blob作为二进制数据

时间:2016-03-14 19:15:11

标签: c++ mysql odbc blob

我有一个带有mediumblob列的MySQL数据库。我想在Windows上使用ODBC将blob字段中的二进制数据转换为C ++字符串流。

我首先调用SQLDescribeCol,表示它的类型为SQL_LONGVARBINARY

然后我按如下方式拨打SQLGetData

SQLLEN indicator;
SQLCHAR SqlChar[8000];
SQLGetData(m_sqlstatementhandle, i, SQL_CHAR, &SqlChar, sizeof(SqlChar), (SQLLEN*)&indicator);

然后我继续将数据写入stringstream

stringstream ss;
ss.write((char*)&SqlChar, indicator);

这确实为我提供了blob数据,但它作为HEX字符串存储在SqlChar中。

我的程序希望stringstream中的数据存储为二进制。现在我可以先将HEX字符串转换为二进制,然后将其写入字符串流,但这对我来说并不合适。我真的希望直接从SQLGetData得到二进制文件。

所以有几个问题:

  1. 我是否正确使用SQLGetData blob类型?
  2. SQLCHAR数组是否是要写入的正确容器?
  3. 有没有办法通过ODBC直接从MySQL获取二进制数据?
  4. 感谢。

2 个答案:

答案 0 :(得分:1)

提供SQL_BINARY作为参数是错误的(即使它在这里工作,因为SQL_BINARYSQL_C_BINARY似乎被定义为相同的值)。来自SQLGetData的文档,关于第3个参数TargetType

  

[Input] * TargetValuePtr的C数据类型的类型标识符   缓冲。有关有效C数据类型和类型标识符的列表,请参阅   附录D:数据类型中的C数据类型部分。

请参阅:https://msdn.microsoft.com/en-us/library/ms715441%28v=vs.85%29.aspx

输入标识符需要标识所用缓冲区的C类型。 c类型标识符的名称都类似于SQL_C_foobar

所以,你应该传递SQL_C_BINARY作为参数(如果你想告诉驱动程序获取普通的二进制数据)或SQL_C_CHAR(如果你想告诉驱动程序转换数据)一些"字符数据")。请注意,SQL_C_CHARSQL_CHAR都定义为1

有关您的情况的更多解释,即驱动程序将数据转换为"字符串":从C数据类型列表中可以看出,可以使用缓冲区类型SQLCHAR对于多个" C类型标识符":如果您使用SQLCHAR缓冲区,并将SQL_C_CHAR作为InputType传递,则驱动程序"知道"缓冲区的类型为SQLCHAR,并且您希望将数据作为"字符数据"。因此,在您的情况下,MySql会将二进制数据转换为人类可读的内容,如十六进制字符串。另一方面,如果您将SQL_C_BINARY作为InputType传递,则驱动程序"知道"缓冲区的类型为SQLCHAR并且您对纯二进制值感兴趣,因此驱动程序无需将二进制数据转换为人类可读的字符串,而只需将缓冲区填充到缓冲区中普通的二进制数据。

请在此处查看c类型列表及其相应的缓冲区类型:https://msdn.microsoft.com/en-us/library/ms714556%28v=vs.85%29.aspx

作为一般性说明:注意文档是否说明" Sql C Type"或者" Sql Type"。第一个用于标识缓冲区的C类型,另一个用于标识列的逻辑数据库类型。

答案 1 :(得分:0)

你有没有花一整天时间试图解决问题,然后在发布问题后20分钟终于找到了答案?我做。

我在this question注意到海报使用的SQL_C_BINARYSQL_BINARY 相同。因此,当我按照以下方式致电SQLGetData时,我得到了我的期望。

SQLGetData(m_sqlstatementhandle, i, SQL_C_BINARY, &SqlChar, sizeof(SqlChar), (SQLLEN*)&indicator);

所以它归结为提供错误的目标类型。

修改 编辑以反映来自@ erg帖子的正确信息。