你确定 LENGTH('中国') = 2吗?
来源:互联网 发布:美国有多强大 知乎 编辑:程序博客网 时间:2024/04/30 16:13
简单描述 LENGTH这个获得字符串长度的函数存在BUG
LENGTH这个PLSQL的基本函数相信大家都很熟悉了,他的功能就是获得指定字符串的字符数。一个中文也算是一个字符。
比如:
SQL> select LENGTH('中国') from dual;
LENGTH('中国')
----------------
2
SQL> select LENGTH('人才168') from dual;
LENGTH('人才168')
-----------------
5
但是,真的 LENGTH('中国')就等于2吗?其实不然,这里面有一个小BUG,大家在程序开发的时候要加以注意。
我使用的数据库版本是Oracle 9.2i.
LENGTH SUBSTR这些函数,我想Oracle内部是有一个判断标识的,用来处理国际字符,但是这些函数在函数内部调用的时候,这些标识某些时候不起作用,下面举例说明:
create table T_CODE_COUNTRY
(
ID VARCHAR2(10) not null,
DESCRIPT VARCHAR2(50) not null,
CHAR_LENGTH NUMBER
);
--添加测试数据
prompt Loading T_CODE_COUNTRY...
insert into T_CODE_COUNTRY (ID, DESCRIPT, CHAR_LENGTH)
values ('1', '塞内加尔', null);
insert into T_CODE_COUNTRY (ID, DESCRIPT, CHAR_LENGTH)
values ('2', '芬兰', null);
insert into T_CODE_COUNTRY (ID, DESCRIPT, CHAR_LENGTH)
values ('3', '1111111111', null);
insert into T_CODE_COUNTRY (ID, DESCRIPT, CHAR_LENGTH)
values ('4', '中国', null);
insert into T_CODE_COUNTRY (ID, DESCRIPT, CHAR_LENGTH)
values ('5', '意大利', null);
commit;
prompt 5 records loaded
--执行UPDATE 操作,更新CHAR_LENGTH字段
UPDATE T_CODE_COUNTRY SET CHAR_LENGTH = TO_CHAR(LENGTH(DESCRIPT));
COMMIT;
SELECT T.* FROM T_CODE_COUNTRY T;
---RESULT LIST
1塞内加尔4
2芬兰2
3111111111110
4中国2
5意大利3
这是正常的结果,但是如果在程序中不可能只用这么简单的标准函数,通常需要自定义函数来处理复杂的逻辑,所以,现在我们把这个LENGTH封装在一个自定义函数中,函数的代码如下:
CREATE OR REPLACE FUNCTION FN_TEST_GET_LENGTH(i_vString IN VARCHAR2)
RETURN VARCHAR2 IS
o_vResult VARCHAR2(300);
BEGIN
o_vResult := TO_CHAR(LENGTH(i_vString));
RETURN o_vResult;
END;
/
再次运行UPDATE语句:
UPDATE T_CODE_COUNTRY SET CHAR_LENGTH =FN_TEST_GET_LENGTH(DESCRIPT);
COMMIT;
SELECT T.* FROM T_CODE_COUNTRY T;
ID DESCRIPT CHAR_LENGTH
---------- ----------------- -----------
1 塞内加尔 4
2 芬兰 2
3 1111111111 10
4 中国 4
5 意大利 6
看到了吧,中国的长度变成了4,BUG出现了,LENGTH的结果不再是字符数,而变成了字节数。大家在编写自定义函数的时候一定要多加小心了。
那么这个问题怎么解决呢?如何避免这个BUG的发生呢?
我目前没有找到特别好的办法,不过还是被我发现了一个比较搞笑的、哭笑不得的解决方案,那就是,把自定义函数的残书中,加一个莫名的,没有用途的参数就可以了,如下:
CREATE OR REPLACE FUNCTION FN_TEST_GET_LENGTH(i_vString IN VARCHAR2,
i_vUnUsed IN VARCHAR2)
RETURN VARCHAR2 IS
o_vResult VARCHAR2(300);
BEGIN
o_vResult := TO_CHAR(LENGTH(i_vString));
RETURN o_vResult;
END;
/
再次运行UPDATE:
UPDATE T_CODE_COUNTRY SET CHAR_LENGTH =FN_TEST_GET_LENGTH(DESCRIPT,NULL);
COMMIT;
SELECT T.* FROM T_CODE_COUNTRY T;
ID DESCRIPT CHAR_LENGTH
---------- ----------------- -----------
1 塞内加尔 4
2 芬兰 2
3 1111111111 10
4 中国 2
5 意大利 3
问题解决了,但是知其然,不知其所以然,知情者请多多指教!
- 你确定 LENGTH('中国') = 2吗?
- 你能快速区分length和length()吗?
- 你确定你要离职吗?
- 你确定你真的懂了line-height吗?
- 并发VS并行,你确定你懂了吗?
- 你知道System.out.println((null+"").length()); 等于多少吗?
- 这种div高度自适应确定你知道吗?
- java中你确定用对单例了吗?
- 中国手机电视国家标准终于确定:T-MMB !, 但CMMB能答应吗?
- 你确定你了解widows文件夹的含义吗?——亲爱的内存溢出
- 知道你的手机是如何确定你的位置的吗
- 你确定你能记住那么多的git命令吗?快试试Sourcetree吧
- 你确定你会用搜索么?
- (转)你确定你的交易系统最快?
- Array#[start, length]=
- [].length = 0
- 中国,你一定要强大!
- 中国你一定要强大!!!!!
- C/C++ 程序设计员应聘常见面试试题深入剖析
- 不要一辈子靠技术生存
- 白乔原创:VC之美化界面篇
- Ghost使用教程
- 如果在国外退休,能拿到多少的薪金?!~~爽啊!
- 你确定 LENGTH('中国') = 2吗?
- Javascript编码风格
- 手动杀SXS.EXE病毒
- Observer设计模式的陷阱,兼谈C++语言在模式面前的悲哀
- 电脑硬盘数据恢复
- 找人( asp.net)
- 这个Flash太酷了!!
- ASP.NET 2.0中使用multiview控件
- 居家旅行杀人越货必备 开发主板的另类功能