2016-06-19 3 views
3

Ich habe eine Datenbank, die Benutzernamen nur auf Englisch im Moment speichert.PLSQL entschlüsseln NVARCHAR2 von BASE64 nach UTF-8

Ich möchte BASE64 & UTF-8, um auch in anderen Sprachen zu speichern, zu übernehmen; Ich möchte es in einer Spalte des Typs NVARCHAR2 speichern.

Die Datenbankprozedur erhält den Namen in BASE64, ich bin Decodierung es über UTL_ENCODE.BASE64_DECODE & die Zeichenfolge VARCHAR2UTL_RAW.CAST_TO_VARCHAR2 mit konvertieren. Aber ich bekomme Kauderwelsch zurück und nicht das eigentliche Wort.

Zum Beispiel bekomme ich 'aleks' als Name in BASE64. Ich bin in der Lage, es zu entschlüsseln, aber die Besetzung zu VARCHAR2/NVARCHAR2 gibt den Wert nicht zurück: Ich bekomme nur Kauderwelsch.

Ich laufe auf Oracle 12c mit NLS_CHARACTERSET WE8ISO8859P1

Hier ist der Code, den ich zu dekodieren verwenden:

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; 

Wie kann ich dies zu überwinden?

+1

Ich bestätige Code: es funktioniert für "normale Zeichen", wie 'abc', aber nicht für Exoten aus Ihrem Beispiel. –

+0

@ J.Chomel, OK, wie kann ich es für exotische arbeiten lassen? –

+0

Ich habe heute viel recherchiert, und ich konnte es nicht überwinden. Ich habe irgendwo gelesen, dass dies von Ihrem Client stammen könnte, der nicht korrekt eingestellt ist, um mit griechischen Zeichen umzugehen. Daher wird DBMS_OUTPUT niemals in der Lage sein, griechische Zeichen auszugeben, egal wie sehr Sie es versuchen. Aber das ist nicht endgültig, da ich es nicht gut verstehe! –

Antwort

2

In erster Linie WE8ISO8859P1 (Westeuropa 8-Bit-ISO 8859 Teil 1, oder - ISO8859 Teil 1) nicht cyryllic Zeichen unterstützen:
siehe diesen Link: https://en.wikipedia.org/wiki/ISO/IEC_8859-1

Deshalb, wenn Sie versuchen, eine Zeichenfolge zu speichern, wie алекс in VARCHAR2 Variable/Spalte, erhalten Sie immer a???? als Ergebnis.

Wahrscheinlich hat jemand während der Installation der Datenbank keine cyrillischen Zeichen berücksichtigt und eine schlechte Codepage gewählt.
Eine bessere Option ISO/IEC 8859-5 (Teil 5) finden Sie unter diesem Link: https://en.wikipedia.org/wiki/ISO/IEC_8859-5

Eine Möglichkeit ist, diese Codierung zu ändern - aber das ist nicht einfach, und es ist beyound dieser Frage.


Was Sie tun können, ist streng NVARCHAR2 Datentyp statt VARCHAR2 Datentyp in allen Orten der Anwendung zu verwenden, die kyrillische Zeichen unterstützen.

Es gibt noch einige Tücken wenn Sie sich bewusst sein müssen:

  • Sie nicht DBMS_OUTPUT Paket Ihren Code debuggen können, weil dieses Paket unterstützen nur VARCHAR2-Datentyp, ist es nicht NVARCHAR
  • Sie unterstützen muss N'some string' Literale (mit N-Präfix) in allen Literalen verwenden ->'алекс' ist VARCHAR2 Datentyp und es wird immer automatisch in 'a????' in Ihrer Codierung konvertiert, während n'алекс' NVARCHAR2 Datentyp ist und eine solche Konvertierung nicht auftritt.

Der Code unten auf Version 12c getestet wird, verwende ich EE8MSWIN1250 Codepage (es desn't auch kyrillische Zeichen unterstützen):

select * from nls_database_parameters 
where parameter like '%CHARACTERSET%'; 

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

es bitte einen Versuch geben:

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; 
/

einige Beispiele:

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лекс 
+0

Brilliant. Funktioniert auf Oracle11g gleich. –

Verwandte Themen