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

OCCI-SQL中'>'表现为'>='及occi::Number类型转换异常问题

问题描述

我在Linux环境使用OCCI 21版本,执行以下查询时,传入表中max值作为参数,预期无结果,但却返回了该max值对应的行:

select * from CacheMessages where message_id > $message_id_p order by message_id, message_number

而在另一张表执行类似查询时结果正确(无返回):

select * from Bank where bank_obj_num > $bank_obj_num

已知条件:

  • 无舍入问题(均为整数值);
  • 数据量少(3500条);
  • 两个查询的参数均为int64类型(约1,260,364,000,000);
  • CacheMessages表有一个由触发器填充的字段(非查询条件字段)。

附CacheMessages表结构及触发器代码:

CREATE TABLE "CACHE_MESSAGES" 
(    "MESSAGE_OBJ_NUM" NUMBER NOT NULL ENABLE, 
    "MESSAGE_TIME" DATE, 
    "MESSAGE_NUMBER" NUMBER, 
    "MESSAGE_ID" NUMBER, 
    "SERIAL_ID" NUMBER, 
    "MESSAGE" VARCHAR2(4000 CHAR), 
     CONSTRAINT "CACHE_MESSAGES_PK" PRIMARY KEY ("MESSAGE_OBJ_NUM", "MESSAGE_TIME")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
  STORAGE(
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) LOCAL
 (PARTITION "CACHE_MESSAGES_MAXV" 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 LOGGING 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "TBS_RNDSAN65" )  ENABLE
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
  STORAGE(
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "TBS_RNDSAN65" 
  PARTITION BY RANGE ("MESSAGE_TIME") 
 (PARTITION "CACHE_MESSAGES_MAXV"  VALUES LESS THAN (MAXVALUE) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING 
  STORAGE(INITIAL 8388608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "TBS_RNDSAN65" ) ;
  CREATE INDEX "CACHE_MESSAGES_IND_01" ON "CACHE_MESSAGES" ("SERIAL_ID") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 
  STORAGE(
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) LOCAL
 (PARTITION "CACHE_MESSAGES_MAXV" 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 LOGGING 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "TBS_RNDSAN65" ) ;
  CREATE OR REPLACE TRIGGER "CACHE_MESSAGES_SERIAL_TRG" 
BEFORE INSERT OR UPDATE
ON CACHE_MESSAGES
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE
iCounter cache_messages.serial_id%TYPE;
cannot_change_counter EXCEPTION;
BEGIN
IF INSERTING THEN
Select cache_messages_serial_seq.NEXTVAL INTO iCounter FROM Dual;
:new.serial_id := iCounter;
END IF;
IF UPDATING THEN
IF NOT (:new.serial_id = :old.serial_id) THEN
RAISE cannot_change_counter;
END IF;
END IF;
EXCEPTION
WHEN cannot_change_counter THEN
raise_application_error(-20000, 'Cannot Change Counter Value');
END;

编辑补充

问题根源似乎出在occi::Number:由于绑定变量是大数值,我使用occi::Number支持的最大类型long double,测试发现异常:将1260365696006存入occi::Number后,转为unsigned long输出得到1260365696005,数值不一致!测试代码如下:

long double ld1 = (long double)1260365696006;
oracle::occi::Number num2(ld1);
LOG("num2=%.9Lf num2(unsigned long)=%ld", (long double)num2, (unsigned long)num2);

// 输出结果:
// num2=1260365696006.000000000 num2(unsigned long)=1260365696005
问题分析与解决

核心原因

查询异常的本质是**occi::Number与long double/unsigned long之间的类型转换精度丢失**:

  • 大整数1260365696006存入occi::Number后,转换为unsigned long时出现向下取整错误,导致实际传入SQL的参数值比预期小1。
  • 这直接解释了message_id > $message_id_p返回max值行的原因:参数实际为max_value - 1,满足max_value > max_value - 1的条件。

为什么另一张表查询正常?

可能是Bank表的bank_obj_num字段值/参数值未触发该转换精度问题,或者该字段采用了直接整数类型绑定而非long double作为中间类型。

解决方法

  1. 规避long double中间类型:对于大整数,直接使用occi::Number的整数安全构造方式:
    // 方式1:字符串构造,彻底避免浮点精度问题
    oracle::occi::Number num2("1260365696006");
    // 方式2:直接传入int64_t类型(OCCI 21版本支持该类型绑定)
    int64_t val = 1260365696006;
    oracle::occi::Number num2(val);
    
  2. 匹配绑定类型:确保SQL参数绑定的类型与数据库NUMBER字段完全匹配,减少不必要的类型转换环节。
  3. 提前验证转换结果:在绑定参数前,验证occi::Number转换回整数的结果是否与原始值一致,避免错误参数传入SQL。

内容的提问来源于stack exchange,提问作者Arnon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 22:47:04