简体   繁体   English

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

[英]How to get a MySQL blob as binary data using SQLGetData in C++

I have a MySQL database with a mediumblob column. 我有一个带有mediumblob列的MySQL数据库。 I want to get binary data from the blob field into a C++ stringstream using ODBC on Windows. 我想在Windows上使用ODBC将二进制数据从blob字段转换为C ++字符串流。

I first call SQLDescribeCol and it indicates that it is of type SQL_LONGVARBINARY . 我首先调用SQLDescribeCol ,它指示它的类型为SQL_LONGVARBINARY

I then make a call to SQLGetData as follows: 然后,我如下调用SQLGetData

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

I then go on and write the data into a stringstream : 然后,我继续将数据写入stringstream

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

This does give me the blob data, but it is stored in SqlChar as a HEX string. 这确实给了我Blob数据,但它以十六进制字符串形式存储在SqlChar中。

My program expects the data in the stringstream to be stored as binary. 我的程序希望将stringstream中的数据存储为二进制。 Now I could convert the HEX string to binary first and then write it to the stringstream, but that doesn't feel right to me. 现在,我可以先将HEX字符串转换为二进制,然后再将其写入字符串流,但这对我来说不合适。 I would really like to get it as binary straight away from SQLGetData . 我真的很想直接从SQLGetData以二进制形式获取它。

So a couple of questions: 有几个问题:

  1. Am I using SQLGetData correctly for a blob type? 我是否为斑点类型正确使用SQLGetData
  2. Is a SQLCHAR array the right container to write into? SQLCHAR数组是要写入的正确容器吗?
  3. Is there a way to get the data as binary directly from MySQL via ODBC? 有没有办法通过ODBC直接从MySQL获取二进制数据?

Thanks. 谢谢。

Supplying SQL_BINARY as argument is wrong (even if it works here because SQL_BINARY and SQL_C_BINARY seems to be defined to the same value). 提供SQL_BINARY作为参数是错误的(即使在这里SQL_BINARY ,因为SQL_BINARYSQL_C_BINARY似乎定义为相同的值)。 From the doc of SQLGetData , about the 3rd argument TargetType : SQLGetData的文档中,关于第三个参数TargetType

[Input] The type identifier of the C data type of the *TargetValuePtr buffer. [输入] * TargetValuePtr缓冲区的C数据类型的类型标识符。 For a list of valid C data types and type identifiers, see the C Data Types section in Appendix D: Data Types. 有关有效的C数据类型和类型标识符的列表,请参见附录D:数据类型中的“ C数据类型”部分。

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

The input identifier needs to identify the C-type of the buffer used. 输入标识符需要标识所用缓冲区的C类型。 The c-type identifier are all named something like SQL_C_foobar . c类型标识符的名称都类似于SQL_C_foobar

So, you should either pass SQL_C_BINARY as argument (if you would like to tell the driver to get plain binary data) or SQL_C_CHAR (if you would like to tell the driver to convert the data to some "character data"). 因此,您应该传递SQL_C_BINARY作为参数(如果您想告诉驱动程序获取纯二进制数据)或SQL_C_CHAR (如果您想告诉驱动程序将数据转换为某些“字符数据”)。 Note that both, SQL_C_CHAR and SQL_CHAR , are defined to 1 . 请注意, SQL_C_CHARSQL_CHAR都定义为1

Some more explanations about your case that the driver converted the data to a "string": As you can see from the list of C Data Types, the buffer-type SQLCHAR can be used for multiple "C type identifiers": If you use a SQLCHAR buffer, and pass SQL_C_CHAR as InputType , the driver "knows" that the buffer is of type SQLCHAR and that you would like to get the data as "character data". 关于驱动程序将数据转换为“字符串”的情况的更多说明:从C数据类型的列表中可以看出,缓冲区类型SQLCHAR可以用于多个“ C类型标识符”:如果使用SQLCHAR缓冲区,并将SQL_C_CHAR作为InputType传递,驱动程序“知道”该缓冲区的类型为SQLCHAR ,并且您希望将数据作为“字符数据”获取。 So, in your case, MySql will convert the binary data to something human-readable, like a hex-string. 因此,在您的情况下,MySql会将二进制数据转换为人类可读的内容,例如十六进制字符串。 On the other hand, if you pass SQL_C_BINARY as InputType , the driver "knows" that the buffer is of type SQLCHAR and that you are interested in pure binary values, so there is no need for the driver to convert the binary data to a human-readable string, and it will just fill the buffer with the plain binary data. 另一方面,如果将SQL_C_BINARY作为InputType传递,则驱动程序“知道”缓冲区的类型为SQLCHAR ,并且您对纯二进制值感兴趣,因此不需要驱动程序将二进制数据转换为人类数据。可读的字符串,它将只用纯二进制数据填充缓冲区。

See here for the list of c-types and their corresponding buffer types: https://msdn.microsoft.com/en-us/library/ms714556%28v=vs.85%29.aspx 有关C类型及其对应的缓冲区类型的列表,请参见此处: https : //msdn.microsoft.com/zh-cn/library/ms714556%28v=vs.85%29.aspx

As a general note: Watch out whether the documentation speaks about the "Sql C Type" or the "Sql Type". 作为一般注意事项:请注意文档是讲“ Sql C类型”还是“ Sql类型”。 The first is used to identify the C-type of a buffer, the other is used to identify the logical database type of a column. 第一个用于标识缓冲区的C类型,另一个用于标识列的逻辑数据库类型。

Do you ever spend all day trying to figure something out, and then finally find the answer 20 minutes after posting your question? 您是否一整天都在尝试找出问题,然后在发布问题20分钟后终于找到答案了? I do. 我做。

I noticed on this question that the poster uses SQL_C_BINARY , which is the same as SQL_BINARY . 我在这个问题上注意到张贴者使用SQL_C_BINARY它与SQL_BINARY相同 So when I call SQLGetData as follows I get what I expect. 因此,当我按如下方式调用SQLGetData ,我得到了期望的结果。

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

So it boiled down to supplying the wrong target type. 因此,归结为提供错误的目标类型。

Edit: Edited to reflect correct information from @erg's post. 编辑:编辑以反映@erg帖子中的正确信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM