在没有查询Unicode值方法,或者没有使用Unicode编辑器的情况下很难使用ASCII字符编写代码。
Oracle9i引入了一个COMPOSE函数,这一函数允许你使用一系列的Unicode字符,并规则化文本。这就意味着,它可以输入一个字母,比如'a' (Unicode字符为0097),以及字符的标记,比如重音符(Unicode字符0300),并建立这两个标记的联合的单一字符。COMPOSE使用特定的联合标记,即Unicode标准,而不是ASCII标点符号。由此其结果为Unicode字符OOEO(具有重音符的小写拉丁字母’a’):
INSI中的绝大部分普通联合字符为:
U+0300: grave accent ( `
)
U+0301: acute accent ( '
)
U+0302: circumflex accent(^)
U+0303: tilde (~)
U+0308: umlaut
在没有其它特定软件或者键盘驱动程序的情况下,很难利用键盘输入Unicode字符0097和0300。所以,在一个纯ASCII文本中输入Unicode字符顺序的一种方法是采用UNISTR函数。这一函数使用一个ASCII字符串,并建立一系列的Unicode字符。它使用十六进制的顺序与任何非ASCII字符相互映射,这与JAVA的方法相类似。
为了输入a字母以及其之后的重音联合字符的次序,你可以使用UNISTR('a 300'),而不是在代码直接输入这些字符。这一函数可以正确地运行在基于Unicode的任何字符集和数据库。你可以在函数中写入更多的联合字符,可以在UNISTR函数中包含ASCII与Unicode字符的混合。例如,可以这样编写:
select COMPOSE(UNISTR('Unless you are nai 308ve, meet me at the
cafe 301 with
your re 301sume 301.')) from dual;
当你使用COMPOSE函数结合函数的输出时,在无需查询每一单一值的情况下,你可以生成一个Unicode字符。例如:
select 'it is true' if compose(unistr('a 300'))
= unistr(' 0e0');
COMPOSE函数返回一个NVARCHAR2字符串,这一字符串通常为Unicode形式。当在本地使用这些字符时,数据库将会企图将这些字符映射到本地字符集,并非所有字符都会被映射,有一些字符不会在COMPOSE函数中操作,因为Unicode社团还没有在Oracle数据库中定义它们。
为了能快速检查特定环境中的字符,你可以运行一个类似于以下代码段的程序,以查看联合字符如何与输出相映射。你需要查找NLS_LANG环境以确保这些字符正确返回:
create or replace type hexrange_tbl as table of varchar2(4);
/
show errors;
create or replace function hexrange(n1 varchar2,n2 varchar2)
returnhexrange_tbl pipelined
is
begin
fori in to_number(n1,'000X') .. to_number(n2,'000X') loop
pipe row(to_char(i,'FM000X'));
end loop;
return;
endhexrange;
/
show errors;
selectcolumn_value composer,
compose(unistr('a'||column_value)) a,
compose(unistr('c'||column_value)) c,
compose(unistr('e'||column_value)) e,
compose(unistr('i'||column_value)) i,
compose(unistr('n'||column_value)) n,
compose(unistr('o'||column_value)) o,
compose(unistr('r'||column_value)) r,
compose(unistr('s'||column_value)) s,
compose(unistr('u'||column_value)) u,
compose(unistr('y'||column_value)) y
from table(hexrange('0300','0327')) x;
这里开个玩笑。这儿一个使用COMPOSE和UNISTR的简短PL/SQL程序,世界上很多SMS用户,黑客,以及Spammers都会利用这一程序使得很多难读的英文文本变得可读性。我使用DBMS_RANDOM任意地选择被用于不同字符的联合字符,然后让SQL生成ANSI/Latin-1输出。
setserveroutput on;
declare
a_combnvarchar2(50) := unistr(' 300 301 302 303 308 30A');
c_combnvarchar2(50) := unistr(' 327');
e_combnvarchar2(50) := unistr(' 300 301 302 308');
i_combnvarchar2(50) := unistr(' 300 301 308');
n_combnvarchar2(50) := unistr(' 303');
o_combnvarchar2(50) := unistr(' 300 301 302 303 308');
u_combnvarchar2(50) := unistr(' 300 301 302 308');
y_combnvarchar2(50) := unistr(' 301 308');
l_idx integer;
l_enamenvarchar2(50);
chnchar;
l_junkvarchar2(50);
begin
dbms_random.initialize(to_char(sysdate,'SSSSS'));
for row in (select ename from emp) loop
l_ename := row.ename;
l_junk := null;
fori in 1..length(l_ename) loop
ch := substr(l_ename,i,1);
case lower(ch)
when 'a' then
l_junk := l_junk || compose(ch || substr(a_comb,
mod(abs(dbms_random.random),length(a_comb)) + 1,1));
when 'c' then
l_junk := l_junk || compose(ch || substr(c_comb,
mod(abs(dbms_random.random),length(c_comb)) + 1,1));
when 'e' then
l_junk := l_junk || compose(ch || substr(e_comb,
mod(abs(dbms_random.random),length(e_comb)) + 1,1));
when 'i' then
l_junk := l_junk || compose(ch || substr(i_comb,
mod(abs(dbms_random.random),length(i_comb)) + 1,1));
when 'n' then
l_junk := l_junk || compose(ch || substr(n_comb,
mod(abs(dbms_random.random),length(n_comb)) + 1,1));
when 'o' then
l_junk := l_junk || compose(ch || substr(o_comb,
mod(abs(dbms_random.random),length(o_comb)) + 1,1));
when 'u' then
l_junk := l_junk || compose(ch || substr(u_comb,
mod(abs(dbms_random.random),length(u_comb)) + 1,1));
when 'y' then
l_junk := l_junk || compose(ch || substr(y_comb,
mod(abs(dbms_random.random),length(y_comb)) + 1,1));
else
l_junk := l_junk || ch;
end case;
end loop;
dbms_output.put_line(to_char(l_junk));
end loop;
end;
/
show errors;
用户评论