通过ADO写入含blob字段MySQL表,报"Column 'xxx' cannot be null"错误的问题

 

1.场景
1.1 程序环境:MySQL 5.0/MySQL ODBC 3.51 Driver/ADO
1.2.测试表
CREATE TABLE `tb_test_12` (
  `f1` int(11) NOT NULL auto_increment,
  `f2` blob NOT NULL,
  `f3` int(11) default NULL,
  PRIMARY KEY  (`f1`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;

1.3 测试代码
int CXBox::OnTest666() {
 GETDBC(pdbor,this->local_dbc_.c_str());
 CRecordset *prs = pdbor->Query(adCmdTable,"tb_test_12");
 bool br;
 br = prs->AddNew();
 br = prs->PutCollect("f3",10l);
 char buffer[32]="sssssss";
 unsigned long len = strlen(buffer);
 br = prs->AppendChunk("f2",(void*)buffer,len);
 ///< @note 到此为止,前面的操作都指示执行成功
 
 br = prs->Update();
 ///< Update失败,错误为:
 ///< [MySQL][ODBC 5.1 Driver][mysqld-5.0.45-community-nt-log]Column 'f2' cannot be null
 const char *err = pdbor->GetLastError();

 return 0;
}

 

2.解决
2.1使用客户端游标,代码如下:
GET_CURSOR_DBC(pdbor,this->local_dbc_.c_str(),CLIENT_CURSOR);

其理由见http://dev.mysql.com/doc/refman/5.1/en/connector-odbc-errors.html#qandaitem-21-1-7-3-1-10
21.1.7.3.10: Using the AppendChunk() or GetChunk() ADO methods, the Multiple-step operation generated errors. Check each status value error is returned.
The GetChunk() and AppendChunk() methods from ADO doesn't work as expected when the cursor location is specified as adUseServer. On the other hand, you can overcome this error by using adUseClient.

对应中文页面 

http://dev.mysql.com/doc/refman/5.1/zh/connectors.html#chunk

 

 

存疑:

.“不能按预期的方式工作”: 是必然得不到预期的结果,还是不能确定得到预期的结果.
.我所见的代码里面有用adUseServer的AppendChunk,从上下文看似乎它应该在实际运行时是工作的,为什么没有暴露问题

.使用GetChunk的代码也未见得使用客户端游标

2.2hotfox.conf配置

 <database encrypted_password="false">
  <conn constr="DRIVER={MySQL ODBC 3.51 Driver};SERVER=127.0.0.1;;OPTION=3;charset=gbk" count="25:2" name="LATON" db_ext="mysql_ext.dll"/>

<count>属性设置采用服务端和客户端游标的连接个数,两者之间用":"分隔。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是用ADO更新BLOB字段的C代码: ``` #include <windows.h> #include <oledb.h> #include <stdio.h> void update_blob_field() { HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr)) { // Connection string for your database char connStr[256] = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\myDatabase.mdb;Persist Security Info=False;"; // Initialize ADO objects IDBInitialize *pInitialize = NULL; IDBCreateSession *pCreateSession = NULL; IDBCreateCommand *pCreateCommand = NULL; hr = CoCreateInstance(CLSID_MSDASQL, NULL, CLSCTX_INPROC_SERVER, IID_IDBInitialize, (void**)&pInitialize); if (SUCCEEDED(hr)) { // Set DB initialization properties hr = pInitialize->Initialize(); if (SUCCEEDED(hr)) { // Create session hr = pInitialize->QueryInterface(IID_IDBCreateSession, (void**)&pCreateSession); if (SUCCEEDED(hr)) { DBPROP rgProps[1]; rgProps[0].dwPropertyID = DBPROP_AUTH_USERID; rgProps[0].dwOptions = DBPROPOPTIONS_REQUIRED; rgProps[0].colid = DB_NULLID; rgProps[0].vValue.vt = VT_BSTR; rgProps[0].vValue.bstrVal = SysAllocString("myUsername"); // Connect to database IDBSession *pSession = NULL; hr = pCreateSession->CreateSession(NULL, IID_IDBSession, (IUnknown**)&pSession); if (SUCCEEDED(hr)) { hr = pSession->SetConnectionProperties(1, rgProps); // Create command pSession->QueryInterface(IID_IDBCreateCommand, (void**)&pCreateCommand); // Issue update command for BLOB field char updateSQL[256] = "UPDATE myTable SET myBlobField = ? WHERE myID = 1"; ICommandText *pCommandText = NULL; hr = pCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**)&pCommandText); if (SUCCEEDED(hr)) { hr = pCommandText->SetCommandText(DBGUID_DBSQL, updateSQL); if (SUCCEEDED(hr)) { // Set up parameter object for BLOB field IColumnsInfo *pColumnsInfo = NULL; pCommandText->QueryInterface(IID_IColumnsInfo, (void**)&pColumnsInfo); DBCOLUMNINFO *pColumnInfo = (DBCOLUMNINFO*)malloc(sizeof(DBCOLUMNINFO)); pColumnsInfo->GetColumnInfo(1, pColumnInfo, NULL, NULL, NULL, NULL); IAccessor *pIAccessor = NULL; pSession->QueryInterface(IID_IAccessor, (void**)&pIAccessor); HACCESSOR hAccessor; pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA, 1, &pColumnInfo->columnid, sizeof(DBPARAMETER), &hAccessor, NULL); DBPARAMETER param; param.dwParameterID = pColumnInfo->columnid; param.dwFlags = 0; param.iid = IID_NULL; param.pTypeInfo = NULL; param.pObject = NULL; param.pwszName = NULL; param.pwszDataSourceType = NULL; // Allocate a buffer for our BLOB data, and fill it with our desired data BYTE *pBlobData = (BYTE*)malloc(100000); // (In practice, you might want to read this data from a file or some other source) for (int i = 0; i < 100000; i++) { pBlobData[i] = (BYTE)(i % 256); } // Set value for BLOB field DBBINDING binding; binding.iOrdinal = 1; binding.dwPart = DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH; binding.eParamIO = DBPARAMIO_INPUT; binding.dwMemOwner = DBMEMOWNER_CLIENTOWNED; binding.dwFlags = 0; binding.cbMaxLen = 100000; binding.cbMaxLen = 100000; binding.wType = DBTYPE_IUNKNOWN; binding.obStatus = 0; binding.obLength = 0; binding.obValue = 0; binding.pTypeInfo = NULL; binding.pObject = NULL; binding.pBindExt = NULL; binding.pDataSourceType = NULL; binding.pBindExt = NULL; binding.pObject = NULL; binding.dwReserved = 0; DBPARAMBINDING paramBinding; paramBinding.dwParamOrdinal = 1; paramBinding.pwszDataSourceType = NULL; paramBinding.dwFlags = 0; paramBinding.pwszName = NULL; paramBinding.iOrdinal = 1; DB_UPARAMS cParams = 1; DBPARAMINFO *rgParamInfo = NULL; DBCOUNTITEM cParamSets = 1; HROWSET hRowset; IRowsetChange *pRowset = NULL; IDBCreateCommand *pCommand = NULL; DBROWCOUNT cRowsAffected = 0; pCommandText->Execute(NULL, IID_IRowsetChange, NULL, &cRowsAffected, (IUnknown**)&pRowset); pCommandText->GetParameterInfo(&cParams, &rgParamInfo); rgParamInfo[0].cbMaxLen = 100000; rgParamInfo[0].dwFlags = 0; paramBinding.cbMaxLen = rgParamInfo[0].cbMaxLen; binding.cbMaxLen = rgParamInfo[0].cbMaxLen; IRowsetChange *pRowsetChange = NULL; pCommandText->QueryInterface(IID_IRowsetChange, (void**)&pRowsetChange); HROW hRow; pRowset->InsertRow(NULL, hAccessor, pBlobData, &hRow); IRowsetChange *pIRowsetChange = NULL; pCommandText->QueryInterface(IID_IRowsetChange, (void**)&pIRowsetChange); pIRowsetChange->SetData(hRow, hAccessor, pBlobData); // Commit transaction ITransactionLocal *pTransaction = NULL; pSession->QueryInterface(IID_ITransactionLocal, (void**)&pTransaction); DBPARAMS params; params.cParamSets = cParamSets; params.hAccessor = hAccessor; params.pData = pBlobData; params.rgParamIO = NULL; params.cbParamIO = 0; params.pVarData = NULL; params.rghCursors = NULL; params.rgRowStatus = NULL; params.hChapter = 0; params.cParamBindings = 1; params.rgParamBindings = &paramBinding; hr = pTransaction->StartTransaction(ISOLATIONLEVEL_READCOMMITTED,ISOLEVEL_CHAOS,0,NULL); hr = pRowsetChange->SetData(hRow, hAccessor, pBlobData); pRowsetChange->Update(hRow, NULL, NULL, &cRowsAffected); hr = pTransaction->Commit(FALSE, XACTTC_ASYNC_PHASEONE, 0); if (!SUCCEEDED(hr)) { printf("Could not commit transaction!"); } // Clean up ADO objects pCommand->Release(); pRowsetChange->Release(); pRowset->Release(); pIRowsetChange->Release(); pIAccessor->Release(); pCommandText->Release(); pColumnsInfo->Release(); CoFreeUnusedLibraries(); CoUninitialize(); free(pColumnInfo); free(pBlobData); } } } } } } } } ``` 请注意,这段代码在编写时并未测试。一些细节可能需要调整和完善,以确保它按您预期的方式运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值