OCCI C++批量插入报ORA-01480错误:绑定值缺失尾随空字符
解决OCCI批量插入时的ORA-01480错误
问题根源分析
ORA-01480错误的核心是Oracle无法找到绑定字符串的终止空字符,你的代码存在两个关键问题:
批量插入数量与实际有效数据不匹配
你通过model.numberOfLinksOfType(linkType)/2提前计算numberOfLinks,但循环中会跳过不符合条件的链接,导致实际有效数据条数(linkIndex)小于预估值。执行executeArrayUpdate(numberOfLinks)时会处理数组中未初始化的无效元素(野指针),这些元素没有合法的终止空字符,触发错误。字符串长度参数设置错误
你将length+1存入长度数组,但OCCI对于OCCI_SQLT_STR类型,要求长度参数为字符串实际字节数(不含终止空字符)。传入length+1会让Oracle认为需要读取更多字节,无法正确识别终止符。
修复方案
1. 使用实际有效数据条数执行批量插入
删除提前计算numberOfLinks的逻辑,先统计有效链接数量,再分配缓冲区并执行插入:
// 初始化有效数据量为0 int numberOfLinks = 0; // 第一步:统计有效链接数量 for (const std::shared_ptr<Link>& link : model.links()) { if (ELinkType::RTN == link->linkType() || (ELinkType::FWD == link->linkType() && ELinkSide::UP == link->linkSide())) continue; numberOfLinks++; }
2. 修正长度数组的值
将长度数组的赋值改为字符串的实际长度(不含终止空字符):
// 原代码:simulationIdBufferLength[linkIndex] = simulationId.length() + 1; // 替换为: simulationIdBufferLength[linkIndex] = simulationId.length(); linkIdBufferLength[linkIndex] = linkId.length(); linkTypeBufferLength[linkIndex] = linkType.length();
3. 仅在有有效数据时执行插入
避免无数据时执行空插入,同时确保所有缓冲区元素都被正确初始化:
if (numberOfLinks > 0) { // 分配缓冲区、填充数据、执行插入的逻辑放在这里 statement->executeArrayUpdate(numberOfLinks); }
完整修复后的核心代码片段
// Open a database connection oracle::occi::Connection* connection = LBCDatabase::instance().getConnection(); int numberOfLinks = 0; char** simulationIdBuffer = nullptr; char** linkIdBuffer = nullptr; char** linkTypeBuffer = nullptr; unsigned short* simulationIdBufferLength = nullptr; unsigned short* linkIdBufferLength = nullptr; unsigned short* linkTypeBufferLength = nullptr; std::string simulationId = model.simulationId(); // 统计有效链接数量 for (const std::shared_ptr<Link>& link : model.links()) { if (ELinkType::RTN == link->linkType() || (ELinkType::FWD == link->linkType() && ELinkSide::UP == link->linkSide())) continue; numberOfLinks++; } if (numberOfLinks > 0) { // 分配缓冲区 simulationIdBuffer = new char*[numberOfLinks]; linkIdBuffer = new char*[numberOfLinks]; linkTypeBuffer = new char*[numberOfLinks]; simulationIdBufferLength = new unsigned short[numberOfLinks]; linkIdBufferLength = new unsigned short[numberOfLinks]; linkTypeBufferLength = new unsigned short[numberOfLinks]; int linkIndex = 0; // 填充数据 for (const std::shared_ptr<Link>& link : model.links()) { if (ELinkType::RTN == link->linkType() || (ELinkType::FWD == link->linkType() && ELinkSide::UP == link->linkSide())) continue; std::string linkId = LBCUtils::restoreLinkId(link->linkId()); std::string linkType = LBCUtils::enumToString<ELinkType>(link->linkType()); simulationIdBuffer[linkIndex] = new char[simulationId.length() + 1]; std::strcpy(simulationIdBuffer[linkIndex], simulationId.c_str()); linkIdBuffer[linkIndex] = new char[linkId.length() + 1]; std::strcpy(linkIdBuffer[linkIndex], linkId.c_str()); linkTypeBuffer[linkIndex] = new char[linkType.length() + 1]; std::strcpy(linkTypeBuffer[linkIndex], linkType.c_str()); // 存储实际字符串长度(不含终止空字符) simulationIdBufferLength[linkIndex] = simulationId.length(); linkIdBufferLength[linkIndex] = linkId.length(); linkTypeBufferLength[linkIndex] = linkType.length(); linkIndex++; } // 执行插入 std::string query("INSERT INTO res_link (simulation_id, link_id, link_type) VALUES(:1, :2, :3)"); oracle::occi::Statement* statement = connection->createStatement(query); statement->setDataBuffer(1, (dvoid*)simulationIdBuffer, oracle::occi::OCCI_SQLT_STR, sizeof(simulationIdBuffer[0]), simulationIdBufferLength); statement->setDataBuffer(2, (dvoid*)linkIdBuffer, oracle::occi::OCCI_SQLT_STR, sizeof(linkIdBuffer[0]), linkIdBufferLength); statement->setDataBuffer(3, (dvoid*)linkTypeBuffer, oracle::occi::OCCI_SQLT_STR, sizeof(linkTypeBuffer[0]), linkTypeBufferLength); statement->executeArrayUpdate(numberOfLinks); connection->commit(); // 清理资源 delete[] simulationIdBufferLength; delete[] linkIdBufferLength; delete[] linkTypeBufferLength; LBCUtils::deleteCharBuffer(simulationIdBuffer, numberOfLinks); LBCUtils::deleteCharBuffer(linkIdBuffer, numberOfLinks); LBCUtils::deleteCharBuffer(linkTypeBuffer, numberOfLinks); connection->terminateStatement(statement); } LBCDatabase::instance().releaseConnection(connection);
内容的提问来源于stack exchange,提问作者user19334409
相关产品推荐
相关产品推荐

