数据库

本类阅读TOP10

·SQL语句导入导出大全
·SQL Server日期计算
·SQL语句导入导出大全
·SQL to Excel 的应用
·Oracle中password file的作用及说明
·MS SQLServer OLEDB分布式事务无法启动的一般解决方案
·sqlserver2000数据库置疑的解决方法
·一个比较实用的大数据量分页存储过程
·如何在正运行 SQL Server 7.0 的服务器之间传输登录和密码
·SQL中两台服务器间使用连接服务器

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
使用COMPOSE和UNISTR 创建沉音字符

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

很多语言,包括英语在内,都使用沉音字符(accented character)。因为这些字符不属于 ASCII 字符集,所以如果不查看 Unicode 值也不使用 Unicode 编辑器并将其转成一个已知字符集,就很难编写使用这些字符的代码。

Oracle9i 引入了 COMPOSE 函数,该函数接受一串 Unicode 字符并规则化其文本。这就意味着它可以接受一个字母和一个组合标记,比如说‘a'(Unicode 字符0097)和沉音符(Unicode 字符0300),然后创建一个单独的由两个标记组合而成的字符。COMPOSE 使用特殊的组合标记,而没有使用 ASCII 中相应的音节标记,它所使用的特殊的组合标记是 Unicode 标准 的一部分。上面的例子的结果应该是 Unicode 字符00E0(有一个沉音符的小写拉丁字母‘a')。

在 ANSI 中最常见的组合字符有:

· U+0300:沉音符(grave accent)( ` )

· U+0301:重音符(acute accent)( ' )

· U+0302:抑扬音符号(circumflex accent)(^)

· U+0303:颚化符号(tilde)(~)

· U+0308:元音变音

如果没有特殊的软件或者键盘驱动程序的话,很难在键盘上输入 Unicode 字符0097和0300。因此,以纯 ASCII 文本输入 Unicode 序列的一个方法是使用 UNISTR 函数。这个函数接受一个 ASCII 字符串然后以国家字符集(通常作为16位 Unicode 或者 UTF-8 字符集安装)创建一个 Unicode 字符的序列。它使用十六进制占位符序列映射任何非 ASCII 字符,映射方式与 Java 类似。

要输入 a 后接一个沉音符组合字符的序列,可以使用 UNISTR(‘a\0300'),而不要试图直接在代码中输入字符。这个函数在任何字符集以及任何具有基于 Unicode 的国家字符集的数据库下都可以正常运行。可以将多个组合字符放在函数中——可以在 UNISTR 函数中混合使用 ASCII 和 Unicode 占位符。例如,可以像下面这样使用 UNISTR 函数:

select COMPOSE(UNISTR('Unless you are nai\0308ve, meet me at the cafe\0301 with
your re\0301sume\0301.')) from dual;

在将 UNISTR 函数的输出与 COMPOSE 组合时,可以在不查找任何值的情况下生成一个 Unicode 字符。例如:

select 'it is true' if compose(unistr('a\0300')) = unistr('\00e0');

COMPOSE 函数返回一个NVARCHAR2 字符串,返回的NVARCHAR2 字符串通常是基于 Unicode 的。如果是在本地使用这些字符,在结果中具有一个隐式地 TO_CHAR 时,数据库将尝试将 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)
return hexrange_tbl pipelined
is
begin
for i in to_number(n1,'000X') .. to_number(n2,'000X') loop
pipe row(to_char(i,'FM000X'));
end loop;
return;
end hexrange;
/
show errors;

select column_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;

下面轻松一下,这里有一小段 PL/SQL 脚本,这段脚本使用COMPOSE 和UNISTR 创建一种特殊效果,很多 SMS 用户、黑客和垃圾邮件发送者都使用这种效果使可读英文文本难于扫描,因为它使用字符重音版本的一个随机序列。我使用DBMS_RANDOM 随机选取一个可由不同字符使用的组合字符,然后让 SQL 进行组合并进行反向转换以生成 ANSI/Latin-1 输出。这段脚本在代码中使用了 EMP 表的 ENAME 字段。

set serveroutput on;
declare
-- these combinations work under ANSI, at least
a_comb nvarchar2(50) := unistr('\0300\0301\0302\0303\0308\ 030A ');
c_comb nvarchar2(50) := unistr('\0327');
e_comb nvarchar2(50) := unistr('\0300\0301\0302\0308');
i_comb nvarchar2(50) := unistr('\0300\0301\0308');
n_comb nvarchar2(50) := unistr('\0303');
o_comb nvarchar2(50) := unistr('\0300\0301\0302\0303\0308');
u_comb nvarchar2(50) := unistr('\0300\0301\0302\0308');
y_comb nvarchar2(50) := unistr('\0301\0308');
l_idx integer;
l_ename nvarchar2(50);
ch nchar;
l_junk varchar2(50);
begin
dbms_random.initialize(to_char(sysdate,'SSSSS'));
for row in (select ename from emp) loop
l_ename := row.ename;
l_junk := null;
for i 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;




相关文章

相关软件