You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OCCI C++批量插入报ORA-01480错误:绑定值缺失尾随空字符

解决OCCI批量插入时的ORA-01480错误

问题根源分析

ORA-01480错误的核心是Oracle无法找到绑定字符串的终止空字符,你的代码存在两个关键问题:

  1. 批量插入数量与实际有效数据不匹配
    你通过model.numberOfLinksOfType(linkType)/2提前计算numberOfLinks,但循环中会跳过不符合条件的链接,导致实际有效数据条数(linkIndex)小于预估值。执行executeArrayUpdate(numberOfLinks)时会处理数组中未初始化的无效元素(野指针),这些元素没有合法的终止空字符,触发错误。

  2. 字符串长度参数设置错误
    你将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:23:15