OCCI处理CHAR类型字符串变量的不同

简介: 问题背景:一个旧应用,原先应用是用proc写的,9i的库,现在应用需要改为使用OCCI,其中有一段查询逻辑:select ... where upper(state)=upper(:1)。

问题背景

一个旧应用,原先应用是用proc写的,9i的库,现在应用需要改为使用OCCI,其中有一段查询逻辑:select ... where upper(state)=upper(:1)。

(此处请不要纠结于where条件中state字段使用了upper函数,因为此表数据量很小,且其历史比较悠久,未建索引。)

对应表中定义的state字段类型是char(3),但此处查询条件变量的值可能是两位,例如'NY'。


现象

1. 使用sqlplus执行select ... where upper(state)=upper(:1)可以正常显示。

2. 使用sql developer执行select ... where upper(state)=upper(:1)可以正常显示。

3. 使用proc执行,可以正常显示。

4. 使用OCCI方式,执行,显示为空


解决

对于使用OCCI的方式,将其改写为:

1. select ... where trim(upper(state)) = trim(upper(:1));

2. select ... where upper(state) = upper(rpad(:1, 3, ' '));


原理推断

1. 首先char和varchar2类型的最大区别,就是char是定长类型,varchar2是不定长类型,网上包括官方文档有很多介绍了,用例子简单讲,就是:

create table test(

a char(25),

b varchar2(25)

);

insert into test values('a', b');

a字段存储的是“a+24个空格”,b字段存储的就是“b”。

可以从select a, length(a), b, length(b) from test;进一步验证。

即char会占用最大的存储空间,varchar2则只会存储实际占用的空间。

2. 从http://www.itpub.net/thread-1014651-1-1.html帖子可以看出,和这个问题相同。推断是OCCI的bug导致。

虽然翻了OCCI的文档,并未找到对这个问题的解释,但从Oracle官方文档对填补空格比较字符串的语义说明,可以看出一些端倪:
Blank-Padded Comparison Semantics
If the two values have different lengths, then Oracle first adds blanks to the end of the shorter one so their lengths are equal. Oracle then compares the values character by character up to the first character that differs. The value with the greater character in the first differing position is considered greater.
If two values have no differing characters, then they are considered equal. This rule means that two values are equal if they differ only in the number of trailing blanks. Oracle uses blank-padded comparison semantics only when both values in the comparison are either expressions of datatype CHAR, NCHAR, text literals, or values returned by the USER function.

Nonpadded Comparison Semantics
Oracle compares two values character by character up to the first character that differs. The value with the greater character in that position is considered greater. If two values of different length are identical up to the end of the shorter one, then the longer value is considered greater. If two values of equal length have no differing characters, then the values are considered equal. Oracle uses nonpadded comparison semantics whenever one or both values in the comparison have the datatype VARCHAR2 or NVARCHAR2.

即对于CHAR、NCHAR类型的字符串比较,Oracle首先会自动补齐空格,然后再一个字符一个字符地比较,不会因为空格数不同认为两者不同,且这个过程应该不是简单的trim()操作,因为如果字段有索引仍会使用。

对于VARCHAR2、NVARCHAR2类型的字符串比较,由于其不会自动存储空格,如果有空格,则也是作为有意义的存储,因此不存在上述问题。

综上所述,对于CHAR类型,不应该因为补空格位数的问题,作为比较的依据,除非使用的where a = trim('a'),人为对值进行处理,因此有理由怀疑OCCI对CHAR类型字符串的比较,至少和其他终端查询的逻辑不同,至于是不是bug,需要看看有没有官方的解释了

目录
相关文章
|
1月前
|
C++
无法将参数1从“const char [6]”转换为“char *”的解决方法
无法将参数1从“const char [6]”转换为“char *”的解决方法
|
7月前
|
存储
关于char类型数组的两种输出方法
关于char类型数组的两种输出方法
145 0
|
人工智能
char类型数组赋值整数,求数组长度
char类型数组赋值整数,求数组长度
106 0
|
存储 测试技术 C语言
C语言中字符串之间的比较【char*】/【string】
C语言中字符串之间的比较【char*】/【string】
852 0
C语言中字符串之间的比较【char*】/【string】
|
JavaScript 前端开发
使用 JavaScript 中的变量、数据类型和运算符,计算出两个 number 类型的变量与一个 string 类型的变量的和,根据 string 类型处于运算符的不同位置得到不同的结果
使用 JavaScript 中的变量、数据类型和运算符,计算出两个 number 类型的变量与一个 string 类型的变量的和,根据 string 类型处于运算符的不同位置得到不同的结果
114 0
使用 JavaScript 中的变量、数据类型和运算符,计算出两个 number 类型的变量与一个 string 类型的变量的和,根据 string 类型处于运算符的不同位置得到不同的结果
|
Java
【Groovy】字符串 ( 字符串类型变量定义 | 字符类型变量定义 )
【Groovy】字符串 ( 字符串类型变量定义 | 字符类型变量定义 )
240 0
【Groovy】字符串 ( 字符串类型变量定义 | 字符类型变量定义 )
char*转换为jstring
char*转换为jstring
180 0
|
存储 Java BI
常量强制数据类型转化
String:不是基本数据类型,是由多的Byte数据类型组成的,原来是由char类型组成的,这里做了优化因为英文字母用ASCLL表示,而ASCLL用Byte类型完全够用,给老外优化的。 常量值也是有类型之说的:整数默认int,小数double,单引号默认char,双引号默认为字符串类型,在Java中大的没办法给小的数据类型,非要给的话声明。
1050 0
|
人工智能 BI
两个字符串 char* a, char* b,输出b在a中的位置次序。
/** 题目: 两个字符串 char* a, char* b,输出b在a中的位置次序。 void output_postion(const char* a, const char* b); 如:a = "abdbcc" b = "abc" ...
1033 0

热门文章

最新文章