Ricerche case sensitive in Oracle 11gR2 e 12cR1

venerdì 22 agosto 2014 alle 22:03 | Pubblicato su 11g, 12c, Diario, Performance Tuning | Lascia un commento
Tag: , ,

Questo post è un aggiornamento del post “Database case sensitive su 10.2.0.3“,  aggiornamento necessario, essendo il post risalente ad oltre sette anni fa. In realtà ho fatto qualche test in questi sette anni ma non ben formalizzato, quando poi mi è stato chiesto per l’ennesima volta se e come era possibile fare ricerche case insensitive su database Oracle (versione 11.2) ho prima dato la solita risposta, poi però mi è venuto lo scrupolo di ricontrollare se fosse cambiato qualcosa sulla versione che attualmente usiamo maggiormente (11.2.0.3 o 11.2.0.4) e sulla nuova 12.1 che installai qualche mese fa per i primi test sulle novità della versione. Riporto sotto il test completo che ho eseguito rispettivamente su un Oracle 10.2.0.5, un 11.2.0.3 e un 12.1.0.1, prima però anticipo alcune conclusioni: con la 11.2.0.3 le cose sono migliorate rispetto alla 10.2, mentre fra la 11.2 e la 12.1 non noto differenze rilevanti, neanche confrontanto velocemente lo stesso capitolo della documentazione nelle tre versioni:

SQL*Plus: Release 12.1.0.1.0 Production on Fri Aug 22 15:57:31 2014

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

PL/SQL procedure successfully completed.

Session altered.

CRISTIAN@geotutf8 > create table test_ci_search (id number,string1 varchar2(30),string2 varchar2(30) ,numero number,data date, datastamp timestamp);

Table created.

CRISTIAN@geotutf8 > create sequence stest_ci_search;

Sequence created.

CRISTIAN@geotutf8 > insert into test_ci_search
2  select stest_ci_search.nextval, dbms_random.string('A',30), dbms_random.string('P',30), dbms_random.random,sysdate, systimestamp
3  from dual connect by level <= 100000;

100000 rows created.

CRISTIAN@geotutf8 > insert into test_ci_search select stest_ci_search.nextval, upper(string1), upper(String2), numero, data,datastamp from test_ci_search;

100000 rows created.

CRISTIAN@geotutf8 > insert into test_ci_search select stest_ci_search.nextval, lower(string1), lower(String2), numero, data,datastamp from test_ci_search where id<=100000
;

100000 rows created.

CRISTIAN@geotutf8 > insert into test_ci_search values (stest_ci_search.nextval,'Cristian','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@geotutf8 > insert into test_ci_search values (stest_ci_search.nextval,'CriStian','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@geotutf8 > insert into test_ci_search values (stest_ci_search.nextval,'CRISTIAN','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@geotutf8 > insert into test_ci_search values (stest_ci_search.nextval,'cristian','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@geotutf8 > commit;

Commit complete.

CRISTIAN@geotutf8 > select * from test_ci_search where string1 ='cristian';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300004 cristian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.832366 PM

CRISTIAN@geotutf8 > ALTER SESSION SET NLS_COMP=LINGUISTIC;

Session altered.

CRISTIAN@geotutf8 > ALTER SESSION SET NLS_SORT=BINARY_CI;

Session altered.

CRISTIAN@geotutf8 > select * from test_ci_search where string1 ='cristian';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300001 Cristian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.012672 PM

300002 CriStian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.031840 PM

300003 CRISTIAN                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.051397 PM

300004 cristian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.832366 PM

CRISTIAN@geotutf8 > select * from test_ci_search where string1 like 'cris%';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300001 Cristian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.012672 PM

300002 CriStian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.031840 PM

300003 CRISTIAN                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.051397 PM

300004 cristian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.832366 PM

CRISTIAN@geotutf8 > create index test_ci_search_idx on test_ci_search (nlssort(string1,'nls_sort=binary_ci'));

Index created.

CRISTIAN@geotutf8 >  set autotrace on
CRISTIAN@geotutf8 > select * from test_ci_search where string1 like 'cris%';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300001 Cristian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.012672 PM

300002 CriStian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.031840 PM

300003 CRISTIAN                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.051397 PM

300004 cristian                       Cudizio                                 1 22-08-2014 15:57:54
22-AUG-14 03.57.54.832366 PM

Execution Plan
----------------------------------------------------------
Plan hash value: 18365057

------------------------------------------------------------------------------------
| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                |    46 |  3772 |   913   (1)| 00:00:11 |
|*  1 |  TABLE ACCESS FULL| TEST_CI_SEARCH |    46 |  3772 |   913   (1)| 00:00:11 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("STRING1" LIKE 'cris%')

Note
-----
- dynamic sampling used for this statement

&nbsp;


C:\tmp>sqlplus cristian/cristian@//10.110.3.52/salespdb

SQL*Plus: Release 12.1.0.1.0 Production on Fri Aug 22 13:08:07 2014

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

ERROR:
ORA-28002: the password will expire within 7 days

Last Successful login time: Wed Apr 09 2014 15:21:53 +02:00

Connected to:
Oracle Database 12c Release 12.1.0.1.0 - 64bit Production

PL/SQL procedure successfully completed.

Session altered.

CRISTIAN@//10.110.3.52/salespdb > create table test_ci_search (id number,string1 varchar2(30),string2 varchar2(30) ,numero number,data date, datastamp timestamp);

Table created.

CRISTIAN@//10.110.3.52/salespdb > create sequence stest_ci_search;

Sequence created.

CRISTIAN@//10.110.3.52/salespdb > insert into test_ci_search
2  select stest_ci_search.nextval, dbms_random.string('A',30), dbms_random.string('P',30), dbms_random.random,sysdate, systimestamp
3  from dual connect by level <= 100000;

100000 rows created.

CRISTIAN@//10.110.3.52/salespdb > insert into test_ci_search select stest_ci_search.nextval, upper(string1), upper(String2), numero, data,datastamp from test_ci_search;

100000 rows created.

CRISTIAN@//10.110.3.52/salespdb > insert into test_ci_search select stest_ci_search.nextval, lower(string1), lower(String2), numero, data,datastamp from test_ci_search wh
ere id<=100000;

100000 rows created.

CRISTIAN@//10.110.3.52/salespdb >
CRISTIAN@//10.110.3.52/salespdb > insert into test_ci_search values (stest_ci_search.nextval,'Cristian','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@//10.110.3.52/salespdb > insert into test_ci_search values (stest_ci_search.nextval,'CriStian','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@//10.110.3.52/salespdb > insert into test_ci_search values (stest_ci_search.nextval,'CRISTIAN','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@//10.110.3.52/salespdb > insert into test_ci_search values (stest_ci_search.nextval,'cristian','Cudizio',1,sysdate,systimestamp);

1 row created.

CRISTIAN@//10.110.3.52/salespdb >
CRISTIAN@//10.110.3.52/salespdb > commit;

Commit complete.

CRISTIAN@//10.110.3.52/salespdb > select * from test_ci_search where string1 ='cristian';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300004 cristian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.484698 PM

CRISTIAN@//10.110.3.52/salespdb > ALTER SESSION SET NLS_COMP=LINGUISTIC;

Session altered.

CRISTIAN@//10.110.3.52/salespdb > ALTER SESSION SET NLS_SORT=BINARY_CI;

Session altered.

CRISTIAN@//10.110.3.52/salespdb > select * from test_ci_search where string1 ='cristian';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300001 Cristian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.457087 PM

300002 CriStian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.466520 PM

300003 CRISTIAN                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.475596 PM

300004 cristian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.484698 PM

CRISTIAN@//10.110.3.52/salespdb > select * from test_ci_search where string1 like 'cris%';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300001 Cristian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.457087 PM

300002 CriStian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.466520 PM

300003 CRISTIAN                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.475596 PM

300004 cristian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.484698 PM

CRISTIAN@//10.110.3.52/salespdb > create index test_ci_search_idx on test_ci_search (nlssort(string1,'nls_sort=binary_ci'));

Index created.

CRISTIAN@//10.110.3.52/salespdb > set autotrace on
ERROR:
ORA-28002: the password will expire within 7 days

SP2-0619: Error while connecting
SP2-0611: Error enabling STATISTICS report
CRISTIAN@//10.110.3.52/salespdb > select * from test_ci_search where string1 like 'cris%';

ID STRING1                        STRING2                            NUMERO DATA
---------- ------------------------------ ------------------------------ ---------- -------------------
DATASTAMP
---------------------------------------------------------------------------
300001 Cristian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.457087 PM

300002 CriStian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.466520 PM

300003 CRISTIAN                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.475596 PM

300004 cristian                       Cudizio                                 1 22-08-2014 13:11:06
22-AUG-14 01.11.06.484698 PM

Execution Plan
----------------------------------------------------------
Plan hash value: 1977262958

----------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name               | Rows  | Bytes | Cost (%CPU)| Time  |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                    |   780 |   159K|  1125   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| TEST_CI_SEARCH     |   780 |   159K|  1125   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | TEST_CI_SEARCH_IDX |  1404 |       |    11   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access(NLSSORT("STRING1",'nls_sort=''BINARY_CI''')>=HEXTORAW('6372697300') AND
NLSSORT("STRING1",'nls_sort=''BINARY_CI''')<HEXTORAW('6372697400'))

Note
-----
- dynamic statistics used: dynamic sampling (level=2)

In sintesi, fino a Oracle 10.2.0.5 era possibile abilitare ricerche su stringhe in modalità case insensitive, il problema era però che dall’uso dell’indice linguistico erano escluso l’operatore LIKE, dalla versione 11.2 in poi invece anche con l’operatore LIKE viene usato l’indice. Ho riportato solo i test per 10.2.0.5 e 12.1.0.1, per 11.2.0.3 il risultato è uguale a quello di 12.1.0.1

Annunci

Oracle Globalization Support – Parte II

lunedì 14 luglio 2008 alle 14:03 | Pubblicato su Installation and Configuration, Oracle Certification | 3 commenti
Tag: , ,

La disponibilità scarsa di frammenti di tempo “libero” che superino la mezz’ora mi porta talvolta a fare dei post frettolosi, come è accaduto per il precedente. D’altra parte se non l’avessi fatto così in fretta probabilmente avrei finito per non farlo affatto.

Prima di proseguire con la panoramica di quello che oracle chiama “Globalization Support” (intendento ciò che è stato fatto per supportare linguaggi, costumi del mondo a livello di database), farò un piccolo riassunto della puntata precedente.

Un primo elemento di supporto alla globalizzazione che un DBMS deve avere è il supporto a più character set. Questo supporto serve per gestire la memorizzazione delle stringhe, del testo, per i numeri e le date non è rilante. Come ho già detto, agli albori dell’informatica moderna un charset a 7 bit come ASCII era sufficente a coprire gran parte degli utilizzi. Un suo “concorrente” fu EBCDIC forse meno noto. Con l’evolversi ed il diffondersi dell’utilizzo dei sistemi informatici i charset sono proliferati per coprire tutte le esigenze, riporto un paio di esempi,  http://www.columbia.edu/kermit/csettables.html dove sono riportate alcune tabelle, ma poi non manca la puntuale informazione della wikipedia, con la voce “Character encoding” e “Code Page“. Ad un certo punto si deciso di fare uno standard globale anche in questo campo ed è nato UNICODE (wikipedia) che ha creato UTF-8. Nel post precedente, basandomi sulla guida Oracle ho affermato che UFT-8 è arrivato alla versione 4.0, in realtà dalla wikipedia apprendo che la versione 4.0 risale all’ormai lontano 2003 e che ad oggi siamo alla 5.1 (abbastanza recente, pare aprile 2008).

Sempre nel post precedente parlando del problema che nasce dalle differenze di charset tra client e server ho fatto l’esempio dell macchina con cui lavoro, su cui è installato l’onnipresente winzoz che si presenta con una code page 850. Questa tabella include in realtà i caratteri usati nei cosiddetti paesi dell’Europa dell’Ovest. E’ un sopra insieme del charset ISO-8859-1 , così pare almeno affermare wikipedia. Essendo però entrambi charset ad un byte desumo, senza mettermi a fare il confronto che coprano lo stesso insieme di caratteri ma che usino una codifica diversa. Invece sempre wikipedia mi conferma che la code page 65001 è equivalente a UTF-8, tant’è che la pagina viene rimandata a quella di UTF-8.

Direi che tutti i riferimenti che ho citato sono sufficenti per chi volesse approfondire ulteriormente i dettagli sui charset.

Tornando al tema principale ricordo che le informazioni dettagliate sul supporto alla globalizzazione nel database oracle sono raccolte in un manuale dedicato a ciò intitolato proprio “Oracle Database Globalization Support Guide” (per 11g e qui). Di questo manuale è il caso di leggere attentamente il capitolo 5, initolato “Linguistic Sorting and String Searching” (per 11g è qui). Il capitolo è importante perchè spiega in sostanza l’utilizzo, il significato ed il settaggio dei due parametri NLS_SORT e NLS_COMP. Essi influiscono rispettivamente sul come vengono fatti gli ordinamenti delle stringhe e su come vengono fatti i confronti. Per default essi hanno entrambi il valore “binary” il che significa che l’ordinamento e il confronto delle stringhe è basato esclusivamente sulla loro codifica numerica (quindi in qualche modo dipende dal charset).

Tempo fa ho affrontato il tema delle ricerche “case insensitive” in oracle (qui e qui) , ovvero le ricerche su stringhe senza distinzione tra maiuscole e minuscole. Come ebbi modo di constatare non c’era modo di fare ricerche case insensitive con il LIKE utilizzando indici. Ebbene segnalo che su 11g invece è possibile. Infatti nel manuale, prima di questo paragrafo è cambiato la nota che prima diceva:

Note:

The SQL functions MAX( ) and MIN( ), and also the LIKE operator, cannot use linguistic indexes when NLS_COMP is set to LINGUISTIC

Che smentiva quanto diceva prima il manule, ora dice:

Note:

The SQL functions MAX( ) and MIN( ) cannot use linguistic indexes when NLS_COMP is set to LINGUISTIC.

Ed  in effetti ho fatto una prova e funziona, provare per credere.

Fino alla 10g essenzialmente i cosiddetti indici linguistici (“Linguistic Index”) servono solo per ricerche per uguaglianza e per ordinamenti.

In ogni caso, come è possibile apprendere dal manuale, sempre dal capitolo 5, oracle prevede una infrastruttura abbastanza sofisticata per gestire i vari metodi di ordinamento in uso in alcune regioni del mondo. Questa infrastruttura è implementata tramit la “Oracle NLS Runtime Library (NLSRTL). Tramite uno strumento chiamato “Oracle Locale Builder” è possibile definire delle personalizzazioni.

Per concludere ricordo le viste di sistema per controllare i settaggi “NLS”:

Sono sicuramente stato superficiale ed incompleto in questa descrizione del Supporto alla Globalizzazione nei database Oracle (Oracle Database Globalization Support) ma non poteva essere altrimenti. Per gli approfondimenti rimando al manuale ed alla pratica.

P.S. (15/07/2008)

Ieri volevo aggiungere anche un ulteriore riferimento, questo thread di discussione su CDOS in cui c’è anche un intervento di Jonathan Lewis che rimanda a due post di Richard Foote, il guru degli indici in Oracle :).

Oracle Globalization Support – Parte I

lunedì 14 luglio 2008 alle 14:07 | Pubblicato su Installation and Configuration, Oracle Certification | 2 commenti
Tag: , ,

Ieri sera, si, domenica sera (i casi della vita) sono riuscito a dedicare un’ora allo studio per l’esame OCP. Non avendo accesso diretto al volume I della “Oracle Database 10g: Administration Workshop II – Student Guide” sono balzato al volume 2 che in realtà contiene solo gli ultimi due capitoli e poi ci sono le esercitazioni pratiche. Gli ultimi due capitoli sono:

  • 15 – Database Security
  • 16 – Globalization Support

Siccome il capitolo “Database Security”  era troppo per una domenica sera sono passato al capitolo 16. Anche questo non è proprio il massimo della vita, ma fa parte del programma, quindi ho sfruttato l’innaturale pace che regnava a casa mia per affrontare questo impegno.

L’argomento è piuttosto noiso, soprattutto perchè per mia fortuna non mi sono dovuto mai scontrare con problematiche di questo tipo (a parte l’utilizzo del character set UTF8). Però essere preparati è sempre utile e ieri sera infatti ho capito e imparato cose nuove.

Character Set

Il primo elemento di supporto alla globalizzazione fornito da Oracle è il supporto a più character set (che spesso abbrevierò con la notazione charset). Il character set non è altro che una tabella di codifica di caratteri grafici (lettere, numeri, simboli, ideogrammi, …) in numeri. Questa tabella è necessaria perchè come sappiamo bene  tutti i computer elaborano solo numeri. Un esempio di charset, forse il più conosciuto è ASCII. In questo caso la tabella di codifica contiene solo 128 elementi, perchè usa solo 7 bit. Chiaramente una simile tabella è insufficente per gestire tutti i metodi di scrittura diffusi nel mondo. Pian piano sono proliferati i charset, quello di Winzoz (ops, windows, ad esempio CP1252 che copre i caratteri usati in italiano (a, b, c, é , …) poi ce ne sono un po’ emessi dall’ISO, ad esempio ISO-8859-p15 che copre i caratteri della lingua italiana e include anche il simbolo dell’euro. Questi charset sono a 8 bit (un byte) e quindi contengono ben 256 elementi. Fin che un database deve essere utilizzato sono in uno stato, quindi con un set ben delimitato di caratteri, non ci sono grandi problemi. Se invece il database è in qualche modo mondiale e deve gestire caratteri che derivano da più nazioni cominciano i problemi. Qui arriva il charset univervale, UTF-8. Si tratta di un charset a lunghezza variabile, superinsieme di ASCII. UTF-8 codifica a un byte tutti i caratteri gia presenti nella tabella ASCII,  poi codifica a 1 o 2 byte il resto dei caratteri utilizzati in europa, poi vi sono una serie di simboli e caratteri asiatici rappresentati a 3 byte, infine vi sono dei caratteri, definiti supplementari codificati con 4 byte. Vi è anche una versione UTF-16, che codifica i caratteri con 2 o 4 byte. Lo standard UTF, viene aggiornato continuamente (credo per aggiungere nuovi caratteri supportati) e attualmente siamo alla versione 4.0, supportata da Oracle e chiamata AL40UTF8. La versione precedente era la 3.2 e in oracle viene chiamata AL32UTF8.

Il grosso problema nella gestione dei charset sta nella comunicazione tra client e server. Anche i terminali che vengono usati come client a loro volta utilizzano dei charset e se questi charset sono diversi da quello usato lato server occorre fare delle conversioni. Oracle a livello  “Oracle Net” cerca di gestire in modo trasparente queste conversioni. In particolare ieri ho capito (forse) meglio cosa significa l’impostazione del charset lato client: essa viene usata da Oracle per fare la conversione, ma l’impostazine deve indicare il charset utilizzato dal terminale, altrimenti si rischia di dare ad Oracle una falsa indicazione inducendolo a fare o non fare una conversione come andrebbe fatto e facendo finire nel database dati invalidi.  Questo meccanismo non mi è ancora completamente chiaro, ma da quel che vedo in giro non sono solo. Il punto è che bisogna proprio fare attenzione alla charset usato dal programma client. Ad esempio se uso sqlplus da una finestra dos in windows e mi collego a un database con charset UTF-8 posso facilmente confondermi se uso ad esempio lettere accentate. Infatti accade che, almeno sulla macchina che uso io,  la tabella dei codici è la 850. Ora, che diavolo di tabella sia non lo so, però so che non è compatibile con UTF-8 e che vengono fuori un saccoi di casini.  Sto ancora cercando di capire bene, ma pare che la tabella 65001 sia compatibile con UTF-8.

Il charset di un database oracle viene definito al momento della creazione e salvo rari casi non è possibile fare una conversione.

NLS_LANG

Oltre le tabelle dei caratteri vi sono altri aspetti che fanno parte del supporto alla globalizzazione: la lingua dei messaggi, la lingua nelle date (i nomi dei giorni della settimana, dei mesi), il formato della data, i separatori per i decimali, il simbolo della valuta, i metodi di ordinamento. In oracle vi è un parametro che permette di impostare queste cose, è NLS_LANG il cui valore ha un formato più meno così:

<language>_<territory>.<charset>

Il linguaggio determina ovviamente la lingua dei vari messaggi, ma anche il linguaggio con cui vengono visualizzati i nomi dei giorni della settimana e i mesi nelle date. L’altro elemento influenzato dal linguaggio è il metodo di ordinamento (vi sono le regole diverse). Questi due elementi possono anche essere settati in modo indipendente trami i parametri NLS_DATE_LANGUAGE e NLS_SORT; il valore di questi due parametri se non settato esplicitamente viene derivato dall’elemento <language> del parametro NLS_LANG.

Dall’elemento <territory> derivano invece i valori dei seguenti parametri:

  • NLS_CURRENCY: il simbolo della valuta, Euro, dollaro, sterlina, yen ecc.
  • NLS_DUAL_CURRENCY
  • NLS_ISO_CURRENCY
  • NLS_DATE_FORMAT
  • NLS_NUMERIC_CHARACTERS, i separatori per i decimali e per le migliaia
  • NLS_TIMESTAMP_FORMAT
  • NLS_TIMESTAMP_TZ_FORMAT

I tre elementi che compongono il valore del parametro NLS_LANG sono opzionali e possono essere specificati singolarmente, ad esempio:

NLS_LANG = _JAPAN

NLS_LANG = .US7ASCII

Infine vi sono dei parametri NLS il cui valore non viene inferito da NLS_LANG:

  • NLS_CALENDAR (mai usato)
  • NLS_COMP (può essere BINARY, il default, ANSI o LINGUISTIC
  • NLS_LENGTH_SEMANTICS, assume importanza fondamentale per i tipi char e varchar in caso di charset multibyte, credo di averne già parlato

Arrivato a questo punto mi rendo conto di aver scritto più quanto avevo preventivato e quindi sarò costretto a esaurire l’argomento in più post (spero bastino due).

Concludo questo post ricordando solo il settaggio dei parametri “NLS” avviene a quattro livelli:

  1. DATABASE
  2. AMBIENTE CLIENT
  3. SESSIONE CLIENT
  4. FUNZIONE SQL

Ma mano che si scende di livello si “sovrascrive” i settaggi del livello superiore.

Crea un sito o un blog gratuitamente presso WordPress.com.
Entries e commenti feeds.