我有一个数据库,目前只用英语存储用户名。
为了在其他语言中存储,我希望合并BASE64
& UTF-8
;我想将它存储在类型为NVARCHAR2
的列中。
数据库过程在BASE64
中接收名称,我正在通过UTL_ENCODE.BASE64_DECODE
解码它&使用UTL_RAW.CAST_TO_VARCHAR2
将字符串转换为VARCHAR2
。但我得到的是胡言乱语,而不是真正的词。
例如,我将'алекс'作为BASE64
中的名称。我能够对其进行解码,但转换为VARCHAR2/NVARCHAR2
并不返回值:我只得到了胡言乱语。
我使用NLS_CHARACTERSET WE8ISO8859P1
在Oracle 12c
上运行
下面是我用来解码的代码:
DECLARE
lv_OrgUserName VARCHAR2(2000);
lv_encodedUserName VARCHAR2(2000);
lv_UserName VARCHAR2(2000);
BEGIN
lv_OrgUserName := 'алекс';
lv_encodedUserName := UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(lv_OrgUserName)));
DBMS_OUTPUT.PUT_LINE (lv_encodedUserName);
lv_UserName := UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW (lv_encodedUserName)));
DBMS_OUTPUT.PUT_LINE (lv_UserName);
END;
我怎样才能克服这一切?
发布于 2016-06-21 09:31:26
首先也是最重要的是,WE8ISO8859P1 (西欧8位ISO 8859 Part 1,或- ISO8859 Part 1)不支持辛辣字符:
请参阅此链接:8859-1
因此,如果尝试将像алекс
这样的字符串存储到VARCHAR2变量/列中,则始终会获得a????
作为结果。
在数据库安装过程中,可能有人没有考虑过西林字符,并且选择了一个不好的代码页。
一个更好的选择是ISO/IEC 8859-5 (第5部分),参见以下链接:8859-5
一种选择是改变这种编码--但这并不容易,也超出了这个问题的范围。
您可以做的是在应用程序中必须支持西里尔字符的所有地方严格使用NVARCHAR2数据类型,而不是VARCHAR2数据类型。
尽管你需要意识到以下几个问题,但仍然存在一些缺陷:
DBMS_OUTPUT
包调试代码,因为此包只支持VARCHAR2数据类型,因此不支持NVARCHARN'some string'
文本(带有N个前缀) --> 'алекс'
是VARCHAR2数据类型,并且总是在编码中自动转换为'a????'
,而n'алекс'
是NVARCHAR2数据类型,并且不会发生这种转换。下面的代码是在12c版本上测试的,我使用的是EE8MSWIN1250
代码页(它也不支持西里尔字符):
select * from nls_database_parameters
where parameter like '%CHARACTERSET%';
PARAMETER VALUE
----------------------- ------------
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_CHARACTERSET EE8MSWIN1250
请试一试:
CREATE OR REPLACE PACKAGE my_base64 AS
FUNCTION BASE64_ENCODE( str nvarchar2 ) RETURN varchar2;
FUNCTION BASE64_DECODE( str varchar2 ) RETURN nvarchar2;
END;
/
CREATE OR REPLACE PACKAGE BODY my_base64 AS
FUNCTION BASE64_ENCODE( str nvarchar2 ) RETURN varchar2
IS
lv_encodedUserName VARCHAR2(2000);
BEGIN
lv_encodedUserName := UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(str)));
RETURN lv_encodedUserName;
END;
FUNCTION BASE64_DECODE( str varchar2 ) RETURN nvarchar2
IS
lv_UserName nVARCHAR2(2000);
BEGIN
lv_UserName := UTL_RAW.CAST_TO_nVARCHAR2(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW (str)));
RETURN lv_UserName;
END;
END;
/
有几个例子:
select 'aлекс' As A, n'aлекс' As B from dual;
A B
----- -----
a???? aлекс
select my_base64.BASE64_ENCODE( n'аaaлекс' ) As aleks from dual;
ALEKS
--------------------------------------------------------------------------------
BDAAYQBhBDsENQQ6BEE=
select my_base64.BASE64_DECODE( 'BDAAYQBhBDsENQQ6BEE=' ) as aleks from dual;
ALEKS
--------------------------------------------------------------------------------
аaaлекс
select my_base64.BASE64_DECODE( my_base64.BASE64_ENCODE( n'аaaлекс' ) ) as Aleks from dual;
ALEKS
--------------------------------------------------------------------------------
аaaлекс
https://stackoverflow.com/questions/37907398
复制相似问题