0

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'

J. Chomel
  • 8,193
  • 15
  • 41
  • 69

2 Answers2

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 "?"

Community
  • 1
  • 1
Wernfried Domscheit
  • 54,457
  • 9
  • 76
  • 110
  • `NLS_NCHAR_CHARACTERSET:AL16UTF16` ; Shame on me, I don't know how to get this NLS_LANG from PLSQL Developper. – J. Chomel Jun 20 '16 at 13:44
  • I think my `NLS_LANG` is `AMERICAN_AMERICA.WE8MSWIN1252` (from windows env. variables) – J. Chomel Jun 20 '16 at 14:01
  • The default codepage set of your `cmd.exe` is (most likely) 850, which does not match `WE8MSWIN1252`. Note, SQL*Plus inherits the codepage settings form parent cmd.exe. They have to match. Btw, here is a solution to change the default codepage of your cmd.exe: http://stackoverflow.com/questions/388490/unicode-characters-in-windows-command-line-how/33475373#33475373 – Wernfried Domscheit Jun 20 '16 at 14:07
  • Thanks, but I can't change registry in here. I'll try by changing NLS_LANG – J. Chomel Jun 20 '16 at 14:10
0

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;
--'κόσμε'
Community
  • 1
  • 1
J. Chomel
  • 8,193
  • 15
  • 41
  • 69