UNISTR vs CHR

 

Questa è curiosità, ma che è importante sapere qualora si dovesse lavorare direttamente con i codici ASCII: non è affatto vero che un carattere è univocamente determinato da un codice numerico, è invece vero che un carattere ha un codice numerico univoco all’interno di un un character set specificato!

Consideriamo il carattere £ (pound): il suo codice ASCII nelle comuni tabelle di riferimento è 163.
Tuttavia CHR(163) = £ solo se il charset del database è WE8ISO8859P1 o WE8MSWIN1252, ma in un database con charset AL32UTF8 la funzione CHR(163) ritorna un carattere diverso, poichè CHR(49827) = £.

Potete controllare le vostre impostazioni:

SELECT *
FROM V$NLS_PARAMETERS
WHERE PARAMETER = 'NLS_CHARACTERSET';

SELECT ASCII('£') FROM DUAL;

SELECT CHR(163) FROM DUAL;

Al posto di CHR(), è consigliabile usare la funzione Oracle UNISTR() che vuole come argomento il codice esadecimale ASCII del carattere da rappresentare e, convertendolo nel codice relativo al charset del database, lo visualizza correttamente. Il codice deve essere passato come stringa di testo in formato ‘XXX’ (leading zeros su 4 cifre, precedute da backslash).

  • Conversione di un carattere (se il charset è AL32UTF8 non ritorna gli stessi valori):

    SELECT UNISTR('0A3'), CHR(163) FROM DUAL;

    Al posto di UNISTR('0A3') si può utilizzare un blocco TO_CHAR(163, 'fm0XXX') che effettua la conversione dell’ASCII 163 nel corrispondente UNICODE esadecimale 00A3.

  • Conversione di una parola con un carattere speciale:

    SELECT UNISTR('Espa\' || TO_CHAR(241, 'fm0XXX') || 'a') FROM DUAL;
    SELECT UNISTR('M\' || TO_CHAR(246, 'fm0XXX') || 'ller') FROM DUAL;

    Le parole España e Möller verranno visualizzate correttamente, indipendentemente dalla configurazione dell’ambiente.

  • A questo punto una funzione che normalizzi le lettere accentate italiane, indipendente dal charset, potrebbe essere:

    CREATE OR REPLACE FUNCTION Normalizza(i_string IN VARCHAR2)
    RETURN VARCHAR2
    IS
      o_string VARCHAR2(4000) := i_string;
    BEGIN
    o_string := REPLACE(o_string, UNISTR('\' || TO_CHAR(224, 'fm0XXX')), 'a');
    o_string := REPLACE(o_string, UNISTR('\' || TO_CHAR(232, 'fm0XXX')), 'e');
    o_string := REPLACE(o_string, UNISTR('\' || TO_CHAR(233, 'fm0XXX')), 'e');
    o_string := REPLACE(o_string, UNISTR('\' || TO_CHAR(236, 'fm0XXX')), 'i');
    o_string := REPLACE(o_string, UNISTR('\' || TO_CHAR(242, 'fm0XXX')), 'o');
    o_string := REPLACE(o_string, UNISTR('\' || TO_CHAR(249, 'fm0XXX')), 'u');
    RETURN o_string;
    END;

 

Lascia un commento