问题
My database has NLS_LANGUAGE:AMERICAN / NLS_CHARACTERSET:WE8ISO8859P15 / NLS_NCHAR_CHARACTERSET:AL16UTF16; NLS_LANG is set to AMERICAN_AMERICA.WE8MSWIN1252 in my Windows> properties> advanced system settings> advanced> environment variables - hope it applies to my PLSQL Dev.
I use ASCIISTR to get a unicode encoded value for exotic chars like this:
SELECT ASCIISTR(N'κόσμε') FROM DUAL;
Results in
ASCIISTR(UNISTR('\03BA\1F79\03...
---------------------------------
\03BA\1F79\03C3\03BC\03B5
It looks like the 'N' means the string is unicode, because if I don't specify it I get it wrong encoded.
SELECT ASCIISTR('κόσμε') FROM DUAL;
Results in
ASCIISTR('??SµE')
--------------------
??s\00B5e
What does this 'N' stands for? How do I invoke it in PLSQL?
I intend to use it on a pl/sql variable to encode exotice characters like this:
DECLARE
l_in VARCHAR2(2000);
l_ec VARCHAR2(2000);
l_dc VARCHAR2(2000);
BEGIN
l_in := 'κόσμε';
execute immediate 'select ASCIISTR(N'''||l_in||''') from dual' into l_ec;
DBMS_OUTPUT.PUT_LINE(l_ec);
select unistr(l_ec) into l_dc from dual;
DBMS_OUTPUT.PUT_LINE (l_dc);
END;
But I get
??s\00B5e
??sµe
As if I were in the second case above, without the 'N'
回答1:
N'κόσμε' is (more or less) equivalent to CAST('κόσμε' AS NVARCHAR2(..))
With N'κόσμε' you say "treat the string as NVARCHAR". If you write just 'κόσμε' then the string is treated as VARCHAR. However, your NLS_CHARACTERSET is WE8ISO8859P15 which does not support Greek characters. Thus you get ? as placeholder.
You didn't tell us your NLS_NCHARACTERSET setting, most likely this supports Unicode.
btw, you don't have to select ... from dual, simply write like
l_ec := ASCIISTR('κόσμε');
in PL/SQL.
What is your local NLS_LANG value, i.e. at your client side? Most likely it does not match the character encoding of your SQL*Plus. See this answer for more details: OdbcConnection returning Chinese Characters as "?"
回答2:
I (sadly) discovered in PLSQL decode NVARCHAR2 from BASE64 to UTF-8 that DBMS_OUTPUT doesn't support NVARCHAR2 datatype. I thusly can't use it to debug.
Then I can do the following to test:
-- encoding
CREATE OR REPLACE FUNCTION my_ec(l_in nvarchar2) RETURN varchar2 is
l_out varchar2(32000);
BEGIN
l_out := asciistr(l_in);
return l_out;
END;
/
-- decoding
CREATE OR REPLACE FUNCTION my_dc(l_in varchar2) RETURN nvarchar2 is
l_out nvarchar2(32000);
BEGIN
l_out := unistr(l_in);
return l_out;
END;
/
with expected result!
select my_ec(N'κόσμε') from dual;
--'\03BA\1F79\03C3\03BC\03B5'
select my_dc('\03BA\1F79\03C3\03BC\03B5') from dual;
--'κόσμε'
select my_dc(my_ec(N'κόσμε')) from dual;
--'κόσμε'
来源:https://stackoverflow.com/questions/37923536/oracle-plsql-equivalent-of-asciistrnstr