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

问题背景

一个旧应用,原先应用是用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,需要看看有没有官方的解释了

时间: 2024-10-13 03:12:01

OCCI处理CHAR类型字符串变量的不同的相关文章

两个char类型的变量的值相等置后的字符串地址

正是因为字符串不是底子类型.并且有时候还会因为地址不相等出现差错的操作,所以要对字符串进行相关操作时会对比费事.因为即使,但是地址空间却不是同一块.例如: 所以为了便当操作以及防止一些差错,<所以为了便当操作以及防止一些差错.<所以为了便当操作以及防止一些差错.C言语中封装了一些可直接对字符串进行操作的函数. 1.      char*strsetchar*str,char i;该函数用字符y替换字符串str中每个字符,回来替换后的字符串地址:例: 回来倒.2.      char*strre

C中变量名通过宏定义转换成char*类型字符串

#include <iostream> p>define name_to_str(name)(#name) int main() { int sum = 10; std::cout<<name_to_str(sum)<<std::endl;//调用宏输出char*型“sum” system("pause"); return 0; }

两个char类型的变量的值持平

恰是由于字符串不是根本类型.而且有时候还会由于地址不持平呈现过错的操作,所以要对字符串进行相关操作时会对比费事.由于即便,但是地址空间却不是同一块.例如: 所以为了便利操作以及避免一些过错,<所以为了便利操作以及避免一些过错.<所以为了便利操作以及避免一些过错.C言语中封装了一些可直接对字符串进行操作的函数. 1.      char*strsetchar*str,char i;该函数用字符y更换字符串str中每个字符,回来更换后的字符串地址:例: 回来倒置后的字符串地址.2.      ch

JavaSE7基础 char类型的变量存储一个汉字

jdk版本  :jdk-7u72-windows-i586系统     :Windows7编辑器   :Notepad++ v7.4.2注意事项 :博文内容仅供参考,不可用于其他用途. 代码 class Demo{ public static void main(String[] args){ char c='给'; System.out.println(c); } } 编译与运行 ------------------------------------------Java,优秀,值得努力学习.

对char类型的理解以及对补码的理解分析

今天遇到这样一个小程序,觉得当中有些问题很容易让人忽略的! 这个程序代码如下: 程序的结果为: 我想很多像我一样的小白可能才开始是想不明白为什么最后的结果是255吧!首先,我们得知道 strlen()是计算字符串长度的函数,但为什么最后得到的字符串长度是255呢?定义的数组a中不是有1000个元素,并且for循环也是执行999次吗? 对于char来说,我们得知道其隐含的结束标记是\0,当编译器识别一个char类型的变量时,读取到\0,则标志着结束:对于这个程序,我们还得注意char的取值围:-1

C++中char类型的溢出问题

C++中什么经常会运用到char类型,也会将char类型作为循环语句的循环条件,但往往这里最容易出现错误,容易出现溢出,进入死循环.这里我们就来简单介绍下为什么会出现这种情况. 首先,了解下char类型的取值范围: char分为无符号(unsigned)和有符号(signed)两种: 无符号(unsigned)的取值范围:0~255: 有符号(signed)的取值范围为:-128~127. 一般我们常用char来声明一个变量,编译器默认为有符号的,即范围为:-128~127. 常见溢出问题: 知

python学习笔记2—python文件类型、变量、数值、字符串、元组、列表、字典

python学习笔记2--python文件类型.变量.数值.字符串.元组.列表.字典 一.Python文件类型 1.源代码 python源代码文件以.py为扩展名,由pyton程序解释,不需要编译 [[email protected] day01]# vim 1.py #!/usr/bin/python        print 'hello world!' [[email protected] day01]# python 1.py hello world! 2.字节代码 Python源码文件

将一个字符串看作一个char类型的数组

有时候我们会遇到将用户输入的一句话中的某一个字符拿出来用的问题. 我们可以将用户输入的字符串看作一个char类型的数组 比如有一个字符串string a = "hello"; 要将'e'输出怎么办? 我们将a看作一个char类型的数组,然后使用for循环来遍历这个数组,然后在控制台中输出即可 for(int i = 0;i<a.Length;i++) { Console.writeLine(a[1]); } 关键是要有将字符串看作char类型数组的思维. 小菜鸟今天的一点小心得,

MFC中字符串赋值出现“Error:“const char*”类型的实参与“LPCWSTR”类型的形参不兼容”错误的解决方法

在编译MFC工程时,写下面代码出现了“Error:“const char*”类型的实参与“LPCWSTR”类型的形参不兼容”的错误. TextOut(hdc,0,0,"Mercedes",strlen("Mercedes")); 这是由于工程采用Unicode编码,这时“Mercedes”字符串类型为“wchar_t*”, 这时应该这样赋值: TextOut(hdc,0,0,_T("Mercedes"),strlen("Mercedes