我在这里遇到了一个我无法理解的错误情况。我写的关于函数的文档也没有什么可以点亮这个东西。
我有一个包含字段titulo varchar2(55)
的表格。我在巴西,这个领域的一些角色有重音符号,我的目标是创建一个没有重音的类似字段(由原始字符替换为á
变为a
等等。 )。
我可以使用一堆函数来执行replace
,translate
和其他功能,但我在互联网上找到一个接口更优雅,然后我使用它。这就是问题所在。
我的更新代码如下:
update myTable
set TITULO_URL = replace(
utl_raw.cast_to_varchar2(
nlssort(titulo, 'nls_sort=binary_ai')
)
,' ','_');
正如我所说,目标是转换其等效的每个重音字符,而没有重音加上_
的空格字符
然后我收到了这个错误:
ORA-12899: value too large for column
"mySchem"."myTable"."TITULO_URL" (actual: 56, maximum: 55)
起初,我可能会添加一些角色,让我检查一下。我做了一个select命令,让我得到titulo
有55个字符的行。
select titulo from myTable where length(titulo) = 55
然后我选择一行来做一些测试,我选择的行有这个值:'FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD'
(我确实改了一下来保存数据,但结果是一样的)
当我执行以下select语句时,事情变得奇怪了:
select a, length(a), b, length(b)
from ( select 'FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD' a,
replace(
utl_raw.cast_to_varchar2(
nlssort('FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD', 'nls_sort=binary_ai')
)
,' ','_') b
from dual
)
这个sql的结果是(为了更好的可视化,我将把值降低一个):
a LENGTH(a)
FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD 55
b LENGTH(b)
fghjtoryo_de_yhjks_da_dghqcaa_de_asga_xcvbgl_easdeonasd 56
比较两个字符串一个在另一个上面,没有大小差异:
FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD
fghjtoryo_de_yhjks_da_dghqcaa_de_asga_xcvbgl_easdeonasd
我已经在Toad,PLSQL Developer和SQLPLUSW上测试了这个查询,结果相同。所以我的问题是这个LENGTH(b)= 56来自?我知道它可以是字符集,但我无法弄清楚为什么。我甚至用trim
命令进行了测试,结果是一样的。
我做过的另一项测试
substr(b, 1,55)
结果与上面的内容相同lenght(trim(b))
结果是56 substr(b,56)
结果为空(没有空,没有空格,只是空)@Sebas建议:
LENGTHB(b)
结果是56 ASCII(substr(b,56))
那么,再次:这个LENGTH(b)= 56来自?
很抱歉这篇长篇文章感谢那些到这里来的人(阅读所有内容)。 感谢那些不读书的人:)
祝你好运
答案 0 :(得分:3)
'nlssort'函数的文档没有声明输出字符串是输入字符串的规范化,或者它们将具有相同的长度。该函数的目的是返回可用于对输入字符串进行排序的数据。
请参阅http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions113.htm#SQLRF51561
很有可能用它来标准化你的字符串,因为显然它有效,但你在这里赌博......
哎呀,它甚至可以产生 LENGTH(b)= 200 而仍然正在做它应该做的事情:)
答案 1 :(得分:1)
1)Oracle区分字节长度和字符长度:varchar2(55)
表示55个字节,因此只有幸运时才有55个UTF-8字符:您应该将字段声明为varchar2 (55 char)
。< / p>
2)像
这样的扭曲replace(utl_raw.cast_to_varchar2(nlssort(
'FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD',
'nls_sort=binary_ai')),' ','_') b
是胡说八道,你只是用类似的字符串替换字符串。 您的数据库有一个编码,所有字符串都用该编码表示,它确定它们的长度(以字节为单位); mcalmeida解释的任意变化引入了随机数据相关的噪声,如果你进行比较,这绝不是一件好事。
3)关于删除重音的规定任务,你应该自己使用REPLACE,TRANSLATE等,因为只有你知道你的要求;它不是Unicode规范化或任何“标准”,没有捷径。 您可以定义一个函数并从任何查询和任何PL / SQL程序中调用它,而不会进行丑陋的复制和粘贴。
答案 2 :(得分:0)
函数“nlssort()”在字符串的原始二进制文件末尾返回带有额外00的二进制文件。
测试:
select NLSSORT('abc') from dual
输出:
61626300
可以通过从NLSSORT的返回中删除最后2位来解决此问题。
解决方案:
select a, length(a), b, length(b)
from ( select 'FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD' a,
replace(
utl_raw.cast_to_varchar2(
substr(nlssort('FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD', 'nls_sort=binary_ai'),1,
length(nlssort('FGHJTÓRYO DE YHJKS DA DGHQÇÃA DE ASGA XCVBGL EASDEÔNASD', 'nls_sort=binary_ai'))-2
)
)
,' ','_') b
from dual
)
)