首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将NVARCHAR2从BASE64解码为UTF-8

将NVARCHAR2从BASE64解码为UTF-8
EN

Stack Overflow用户
提问于 2016-06-19 12:48:13
回答 1查看 3.5K关注 0票数 3

我有一个数据库,目前只用英语存储用户名。

为了在其他语言中存储,我希望合并BASE64 & UTF-8;我想将它存储在类型为NVARCHAR2的列中。

数据库过程在BASE64中接收名称,我正在通过UTL_ENCODE.BASE64_DECODE解码它&使用UTL_RAW.CAST_TO_VARCHAR2将字符串转换为VARCHAR2。但我得到的是胡言乱语,而不是真正的词。

例如,我将'алекс'作为BASE64中的名称。我能够对其进行解码,但转换为VARCHAR2/NVARCHAR2并不返回值:我只得到了胡言乱语。

我使用NLS_CHARACTERSET WE8ISO8859P1Oracle 12c上运行

下面是我用来解码的代码:

代码语言:javascript
运行
复制
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;

我怎样才能克服这一切?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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数据类型,因此不支持NVARCHAR
  • 您必须在所有文本中使用N'some string'文本(带有N个前缀) --> 'алекс'是VARCHAR2数据类型,并且总是在编码中自动转换为'a????',而n'алекс'是NVARCHAR2数据类型,并且不会发生这种转换。

下面的代码是在12c版本上测试的,我使用的是EE8MSWIN1250代码页(它也不支持西里尔字符):

代码语言:javascript
运行
复制
select * from nls_database_parameters
where parameter like '%CHARACTERSET%';

PARAMETER                VALUE
-----------------------  ------------
NLS_NCHAR_CHARACTERSET   AL16UTF16
NLS_CHARACTERSET         EE8MSWIN1250

请试一试:

代码语言:javascript
运行
复制
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;
/

有几个例子:

代码语言:javascript
运行
复制
select 'aлекс' As A, n'aлекс' As B from dual;

A     B   
----- -----
a???? aлекс
代码语言:javascript
运行
复制
select my_base64.BASE64_ENCODE( n'аaaлекс' ) As aleks from dual;

ALEKS                                                                          
--------------------------------------------------------------------------------
BDAAYQBhBDsENQQ6BEE= 
代码语言:javascript
运行
复制
select my_base64.BASE64_DECODE( 'BDAAYQBhBDsENQQ6BEE=' ) as aleks from dual;

ALEKS                                                                          
--------------------------------------------------------------------------------
аaaлекс   
代码语言:javascript
运行
复制
select my_base64.BASE64_DECODE( my_base64.BASE64_ENCODE( n'аaaлекс' ) ) as Aleks from dual;

ALEKS                                                                          
--------------------------------------------------------------------------------
аaaлекс  
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37907398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档