Novità sulla gestione dello spazio in Oracle 11gR2

venerdì 30 maggio 2014 alle 30:22 | Pubblicato su 11g | 1 commento

Sono un po’ indietro,  questo spiega un post su una novità introdotta con Oracle 11gR2 (in realtà parte con 11.2.0.2) a diversi mesi dall’uscita di oracle 12c. Sto cercando di non rimanere indietro e di non perdermi informazioni, quindi sto ripassando il manuale “Oracle® Database New Features Guide” versione 11gR2, quando avrò finito con quello potrò permettermi di passare all’equivalente manuale versione 12c R1. La maggior parte delle nuove funzionalità e caratteristiche introdotte da Oracle non mi interessa, cerco di contentrarmi su quelle che posso sfruttare utilmente, senza sprecare risorse a studiare a tappeto tutto. Una su cui secondo me vale la pena soffermarsi, o meglio due, sono la gestione dello spazio, tramite l’uso del comando “TRUNCATE” e tramite l’uso del package DBMS_SPACE_ADMIN.

Il comando TRUNCATE è stato esteso per poter richiedere o  meno il rilascio dello spazio allocato dalla tabella. Il comando usato come nelle versioni precedenti, ad esempio:


TRUNCATE TABLE test_truncate;

Si comporta come nelle versioni precedenti di Oracle (lasciando allocati gli extent eventualmente indicati con il parametro MINEXTENT). Quanto sopra è equivalente, con la nuova estensione a:


TRUNCATE TABLE test_truncate DROP STORAGE;

Vi sono poi due possibilità nuove, la prima è lasciare lo spazio allocato per la tabella allocato, in tal caso il comando usa l’opzione “REUSE STORAGE”:


TRUNCATE TABLE test_truncate REUSE STORAGE;

All’estremo opposto vi è la possibilità di rilasciare tutto, ma proprio tutto lo spazio allocato dalla tabella eliminando il segmento, in questo caso l’opzione è “DROP ALL STORAGE”:


TRUNCATE TABLE test_truncate DROP ALL STORAGE;

Cerco di riportare un po’ di esempi per fare capire meglio.


SVILUPPO40@SVIL112_METHONE > create table test_truncate(a number, b varchar2(4000));

Table created.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name = 'TEST_TRUNCATE' ;

no rows selected

SVILUPPO40@SVIL112_METHONE > begin
2  for i in 1..10000 loop
3  insert into test_truncate values (1,rpad('testxx',4000,'z'));
4  end loop;
5  end;
6  /

PL/SQL procedure successfully completed.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

SEGMENT_NAME                                                                              MB
--------------------------------------------------------------------------------- ----------
TEST_TRUNCATE                                                                             80

SVILUPPO40@SVIL112_METHONE > TRUNCATE TABLE test_truncate REUSE STORAGE;

Table truncated.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

SEGMENT_NAME                                                                              MB
--------------------------------------------------------------------------------- ----------
TEST_TRUNCATE                                                                             80

SVILUPPO40@SVIL112_METHONE > TRUNCATE TABLE test_truncate ;

Table truncated.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

SEGMENT_NAME                                                                              MB
--------------------------------------------------------------------------------- ----------
TEST_TRUNCATE                                                                          .0625

SVILUPPO40@SVIL112_METHONE > TRUNCATE TABLE test_truncate REUSE STORAGE;

Table truncated.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

SEGMENT_NAME                                                                              MB
--------------------------------------------------------------------------------- ----------
TEST_TRUNCATE                                                                          .0625

SVILUPPO40@SVIL112_METHONE > TRUNCATE TABLE test_truncate DROP ALL STORAGE;

Table truncated.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

no rows selected

SVILUPPO40@SVIL112_METHONE > DROP TABLE TEST_TRUNCATE PURGE;

Table dropped.


SVILUPPO40@SVIL112_METHONE > create table test_truncate(a number, b varchar2(4000)) STORAGE (MINEXTENTS 100);

Table created.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

no rows selected

SVILUPPO40@SVIL112_METHONE > INSERT INTO test_truncate values (1,'a');

1 row created.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

SEGMENT_NAME                                                                              MB
--------------------------------------------------------------------------------- ----------
TEST_TRUNCATE                                                                            104

SVILUPPO40@SVIL112_METHONE > TRUNCATE TABLE test_truncate;

Table truncated.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

SEGMENT_NAME                                                                              MB
--------------------------------------------------------------------------------- ----------
TEST_TRUNCATE                                                                            104

SVILUPPO40@SVIL112_METHONE > TRUNCATE TABLE test_truncate DROP ALL STORAGE;

Table truncated.

SVILUPPO40@SVIL112_METHONE > select SEGMENT_name,BYTES/1024/1024 MB from user_segments where segment_name like '%TEST_TRUNCATE' ;

no rows selected

SVILUPPO40@SVIL112_METHONE >

Parallelamente al package DBMS_SPACE_MANAGEMENT sono state aggiunte due procedure:

  1. DROP_EMPTY_SEGMENTS
  2. MATERIALIZE_DEFERRED_SEGMENTS

Il primo può essere utile in caso di database migrati, in cui ci sono magari un sacco di tabelle vuote per cui, provenendo da versioni Oracle precedenti alla 11.2 dove non esisteva la “deferred segment creation”, vengono comunque creati i segmenti. Va detto che nei miei casi si tratta comunque di briciole di spazio per cui non so quanto valga la pena rompersi, ma se uno vuole raschiare il fondo così può farlo :-) Il package DBMS_SPACE_ADMIN anche se non scritto in modo chiarissimo sul manuale, mi risulta utilizzabile solo da utente SYS, invocando la procedure DROP_EMPTY_SEGMENTS specificando solo il primo parametro (lo schema) viene spazolato tutto lo schema e per le tabelle vuote vengono eliminati i segmenti, altrimenti è possibile specificare le tabelle per cui si vuole agire.

L’utilità della procedura MATERIALIZE_DEFERRED_SEGMENTS mi viene ancora più difficile da immaginare, comunqu, per completezza fa esattamente il contrario della precedente, crea il segmento di partenza per tutte le tabelle.

Nome del file o estensione troppo lunga in Windows

mercoledì 28 maggio 2014 alle 28:05 | Pubblicato su Diario | Lascia un commento

Evidentemente non potrò mai essere un buon programmatore, perché non so usare gli “IDE”; ieri ho provato a giocchicchiare un po’ con Netbeans 7.3 e cercando di aggiungere delle librerie al progetto ho fatto evidententemente qualcosa di sbagliato, tant’è che ho dovuto uccidere il programma perché non ne usciva più. Stamattina ho deciso di riprovarci ed ho cominciato con il fare pulizia, trovandomi però con un bizzarro problema: all’interno della directory dove dovevano stare le librerie Netbeans aveva creato ricorsivamente decine, forse centinaia di directory innestate con lo stesso nome, una cosa tipo C:\progetto\lib\lib\lib\lib\lib\…

Bisogna sapere che quando il percorso assoluto di un file in windows supera i 260 caratteri windows non è più in grado di gestirlo e cercando di rimuoverlo si ottiene un errore tipo quello che da il titolo a questo post, sia provando da Explorer che da linea di comando. C’è da chiedersi perché windows ne permetta la creazione ma poi non sia capace di gestirli… Lo stesso problema può capitare con un nome di file troppo lungo, in questo caso però forse si riesce a fare la rinomina, non ne sono sicuro.

Ho iniziato allora dopo tentativi da linea di comando svariati a cercare su internet ma le soluzioni trovate facendo una ricerca per il testo dell’errore in italiano non funzionavano per la mia situazione, quindi ho provato a fare la ricerca traducendo (alla meno peggio) in inglese il testo del messaggio, quindi con i termini “filename or extension too long” alla fine sono arrivato a questa pagina (parrebbe un forum ufficiale microsoft, in precedenza ero capitato sullo stesso sito ma su una discussione in italiano dove non si fornivano soluzioni..). Qui si propone come soluzione l’uso di Cygwin e del comando “rm”, io ho provato con il comando rm che trovo gia installato su Windows 7, senza aver mai installato Cygwin ma non funziona, stesso errore, prima di provare allora a installare Cygwin ho continuato a scorrere la discussione fino alla soluzione proposta da “Augustin Botana” (avrei volentieri messo il link alla singola risposta, ma evidentemente in MS non conoscono queste feature così avanzate …) il quale spiega di avere avuto lo stesso problema con netbeans, mi permetto di citare il suo intervento:

Hi.

I had the same problem but with netbeans which built recursive folders with the root given name. I used the name “mermelada” under my c:\temp\ folder.

I had thousands (at least) of c:\temp\mermelada\mermelada…. And so and not able to delete because the windows “name too long” message.

I used the inspiration of another user of this issue and made a recupera2.bat with the following content

ren c:\temp\mermelada\mermelada\mermelada x

move c:\temp\mermelada\mermelada\x c:\temp\mermelada

rd c:\temp\mermelada\mermelada

ren c:\temp\mermelada\x mermelada

recupera2.bat

In a DOS window, I ran c:\recupera2.bat, leaved alone for 2 minutes and voila!… just a empty “mermalada” folder  ready to be destroyed.

Good luck!

 

Ecco, la soluzione è geniale, uno script ricorsivo, l’ho adattato al mio caso ed ha funzionato benissimo

Database server con più “Time Zone”

lunedì 19 maggio 2014 alle 19:52 | Pubblicato su Diario | Lascia un commento
Tag: ,

Recentemente mi è stata commissionata un’indagine su come è possibile gestire più “Time Zone” su un database Oracle o più database Oracle sulla stessa macchina, siccome il risultato delle mie indagini mi è parso interessante e ho voglia di organizzare tale risultato al fine di trovare più rapidamente le informazioni la prossima volta che mi serviranno (se mai capiterà) ho deciso di scrivere questo post riepilogativo.

Quando mi è stato sottoposto il problema ho deciso di partire subito dal supporto Oracle, partendo dalla presunzione che per una singola istanza Oracle non fosse possibile “vedere” più time zone contemporaneamente. Quindi ho iniziato con una ricerca per i termini “multiple instances different timezones” ed ho cominciato con il primo documento rilevante che è:

How to use multiple timezones with one Oracle RAC database (Doc ID 1531653.1)

Nel mio caso non si usa RAC, quindi sono passato subito al primo documento indicato dopo poche righe:

How To setup TNS listener to Show More Than one Timezone (Doc ID 399448.1)

Questo è stato il primo documento che mi ha fatto pensare: “questo è interessante e me lo devo segnare”. In esso viene spiegato come, ad esclusione di ambienti Windows, dove a causa dell’architettura monoprocesso/multithread la soluzione non funziona, è possibile avviare per una singola istanza Oracle più listener, ciascuno dei quali fa vedere ai client collegati il database su una specifica “time zone” specificata sotto forma di variabile d’ambiente TZ nella configurazione del listener sul file listener.ora. La variabile TZ viene passata i processi server che vengono creati su richiesta del listener per soddisfare la richiesta di connessione. Questo funziona solo se non si usano “Shared Server” (perché in quel caso non c’è la creazione del nuovo processo, do’ per scontata la conoscenza dei meccanismi Oracle per la gestione delle richieste di connessione in caso di “dedicated server” e “shared server”). Altra condizione indicata nel documento è che la connessione avvenga tramite SID, su questo non ho indagato in realtà, ma non essendo un problema l’ho preso per buono.

Per fare qualche controllo mi sono ripassato e riporto altri interessanti documenti:

Dates & Calendars – Frequently Asked Questions (Doc ID 227334.1)

Timestamps & time zones – Frequently Asked Questions (Doc ID 340512.1)

Database Timezone Configuration (Doc ID 745854.1)

Ci sono cose che ho gia riassunto in un mio vecchio post e altro. Alla fine pare che la Time Zone del server influisca solo sulle funzioni SYSDATE e SYSTIMESTAMP, nel senso che l’ora del server verrà presentata al client nella time zone impostata; per il resto al client che si collega al database cambia poco (direi nulla, ma metto in conto possa essermi sfuggito qualcosa).

Oracle 12c: top n query e default

giovedì 16 gennaio 2014 alle 16:13 | Pubblicato su 12c, SQL | 4 commenti
Tag: , ,

Questo post nasce da un lungo giro, come mi è capitato più volte in passato; ieri approfittando di un momento di calma ho dato una occhiata ai miei “feed”, strumento che ormai pare obsoleto e rimpiazzato per i più (ma non da me) da twitter che però non ritengo possa rimpiazzare come funzionalità l’accopiata blog+feed, direi anzi che twitter va verso la direzione di creare confusione e far perdere informazioni preziose… ma sto divagando. Ieri quindi ho dato una letta a qualche articolo sui blog che seguo ormai da anni e che parlano di database Oracle, in particolare leggevo gli ultimi post di Jonathan Lewis, che rappresenta ancora una preziosissima risorsa. Finito di leggere un post l’occhio mi è caduto sul blogroll che in testa riporta questo interessante link; si tratta di una pagina in cui a sua volta sono raggruppati un sacco di link a fonti di informazione sul nuovo Oracle 12c. Scorrendo i link mi sono soffermato su questo, non tanto per l’argomento quanto per l’autore che mi era un nome noto. Arrivato al post di Connor Mcdonald l’argomento mi ha incuriosito e sono andato alla sua fonte, un articolo di Tom Kyte. Come si vede un giro abbastanza lungo (almeno per il livello medio di molti utilizzatori di internet); comunque sull’articolo di Tom Kyte ho deciso di approfondire. Ho così rispolverato la macchina virtuale con Oracle 12c, mi ci è voluto un attimo per riorientarmi e trovare il container, creare un utente (e prima una tablespace dedicata), poi sono riuscito a ripetere gli esempi mostrati, prima sui Default sui valori delle colonne nelle tabelle, dove Oracle ha sicuramente colmato una lacuna, permettendo di definire come valore di default per una colonna il numero generato da una sequence, creata esplicitamente e separatamente o implicitamente e legata alla tabella con la specifica “generated as [default] identity“. Un po’ più bizzarra la funzionalità “default on NULL” che però evidentemente per molti può risultare utile. Non ho testato la miglioria sull’aggiunta di colonne con valori di default, ma sembra anche essa una grande cosa (ho passato brutti momenti in passato con l’aggiunta di colonne con valore di default a tabelle molto grandi).

Infine l’argomento “top n query“: anche questo mi è  parso interessante, finché non ho notato una differenza fra le mie prove e quanto mostrato da Tom. Ho ripetuto le prove anche su una precedente installazione di Oracle 12c in cui ho installato Enterprise Edition (mentre in ambiente virtuale ho installato una standard edition per fare prove sulla “Multitenant Architecture“) e il risultato è diverso da quello mostrato di Tom, a livello di piano di esecuzione, ecco i miei risultati:

CRISTIAN@10.110.3.52/salespdb > create table t2 as select * from all_objects;

Table created.

CRISTIAN@10.110.3.52/salespdb > create index idx_t2 on t2(owner,object_name);

Index created.

CRISTIAN@10.110.3.52/salespdb > select owner,object_name,object_id from t2
 2 order by owner,object_name fetch first 5 rows only;

OWNER OBJECT_NAME OBJECT_ID
----------------------------- ------------------------------ ----------
APEX_040200 APEX 87057
APEX_040200 APEXWS 86726
APEX_040200 APEX_ADMIN 88996
APEX_040200 APEX_APPLICATIONS 87697
APEX_040200 APEX_APPLICATION_ALL_AUTH 87765

Elapsed: 00:00:00.07

Execution Plan
----------------------------------------------------------
Plan hash value: 3975347511

-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 76285 | 21M| | 1101 (1)| 00:00:01 |
|* 1 | VIEW | | 76285 | 21M| | 1101 (1)| 00:00:01 |
|* 2 | WINDOW SORT PUSHED RANK| | 76285 | 2756K| 3600K| 1101 (1)| 00:00:01 |
| 3 | TABLE ACCESS FULL | T2 | 76285 | 2756K| | 362 (1)| 00:00:01 |
-----------------------------------------------------------------------------------------

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

1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=5)
 2 - filter(ROW_NUMBER() OVER ( ORDER BY "OWNER","OBJECT_NAME")<=5)


Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 1300 consistent gets
 0 physical reads
 0 redo size
 614 bytes sent via SQL*Net to client
 475 bytes received via SQL*Net from client
 2 SQL*Net roundtrips to/from client
 1 sorts (memory)
 0 sorts (disk)
 5 rows processed

La cosa che mi “perprime” è che con la classica tecnica del ROWNUM ho questo:


CRISTIAN@10.110.3.52/salespdb > select * from ( select owner,object_name,object_id from t2
 2 order by owner,object_name) where rownum<=5;

OWNER OBJECT_NAME OBJECT_ID
----------------------------- ------------------------------ ----------
APEX_040200 APEX 87057
APEX_040200 APEXWS 86726
APEX_040200 APEX_ADMIN 88996
APEX_040200 APEX_APPLICATIONS 87697
APEX_040200 APEX_APPLICATION_ALL_AUTH 87765

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 2015243804

----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 725 | 8 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | VIEW | | 5 | 725 | 8 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| T2 | 76285 | 2756K| 8 (0)| 00:00:01 |
| 4 | INDEX FULL SCAN | IDX_T2 | 5 | | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------

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

1 - filter(ROWNUM<=5)


Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 9 consistent gets
 0 physical reads
 0 redo size
 614 bytes sent via SQL*Net to client
 475 bytes received via SQL*Net from client
 2 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 5 rows processed

Nel mio caso non usa l’indice, mi è venuto lo scrupolo di provare a vedere le statistiche e il costo del piano usando un hint per forzare l’uso dell’indice:


CRISTIAN@10.110.3.52/salespdb > select /*+ INDEX(T2 IDX_T2) */owner,object_name,object_id from t2
 2 order by owner,object_name fetch first 5 rows only;

OWNER OBJECT_NAME OBJECT_ID
----------------------------- ------------------------------ ----------
APEX_040200 APEX 87057
APEX_040200 APEXWS 86726
APEX_040200 APEX_ADMIN 88996
APEX_040200 APEX_APPLICATIONS 87697
APEX_040200 APEX_APPLICATION_ALL_AUTH 87765

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 2588503356

----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 76285 | 21M| 62581 (1)| 00:00:03 |
|* 1 | VIEW | | 76285 | 21M| 62581 (1)| 00:00:03 |
|* 2 | WINDOW NOSORT STOPKEY | | 76285 | 2756K| 62581 (1)| 00:00:03 |
| 3 | TABLE ACCESS BY INDEX ROWID| T2 | 76285 | 2756K| 62581 (1)| 00:00:03 |
| 4 | INDEX FULL SCAN | IDX_T2 | 76285 | | 454 (1)| 00:00:01 |
----------------------------------------------------------------------------------------

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

1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=5)
 2 - filter(ROW_NUMBER() OVER ( ORDER BY "OWNER","OBJECT_NAME")<=5)


Statistics
----------------------------------------------------------
 1 recursive calls
 0 db block gets
 9 consistent gets
 0 physical reads
 0 redo size
 614 bytes sent via SQL*Net to client
 475 bytes received via SQL*Net from client
 2 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 5 rows processed

Le statistiche sono migliorate, ma il costo indicato per il  piano di esecuzione è elevato. Come spiega bene Christian Antognini sul suo libro “Troubleshooting Oracle Performance” (e come la mia esperienza conferma) piani di esecuzione non ottimali molto spesso sono generati da previsioni sbagliate, infatti (ma si intravedeva gia prima):

</pre>
CRISTIAN@10.110.3.52/salespdb > select /*+ gather_plan_statistics */ owner,object_name,object_id from t2
 2 order by owner,object_name fetch first 5 rows only;

OWNER OBJECT_NAME OBJECT_ID
----------------------------- ------------------------------ ----------
APEX_040200 APEX 87057
APEX_040200 APEXWS 86726
APEX_040200 APEX_ADMIN 88996
APEX_040200 APEX_APPLICATIONS 87697
APEX_040200 APEX_APPLICATION_ALL_AUTH 87765

Elapsed: 00:00:00.07
CRISTIAN@10.110.3.52/salespdb > select plan_table_output from table(dbms_xplan.display_cursor(null, null, 'allstats last'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID g467gxjwprt0g, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ owner,object_name,object_id from
t2 order by owner,object_name fetch first 5 rows only

Plan hash value: 3975347511

----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.04 | 1300 | | | |
|* 1 | VIEW | | 1 | 76285 | 5 |00:00:00.04 | 1300 | | | |
|* 2 | WINDOW SORT PUSHED RANK| | 1 | 76285 | 5 |00:00:00.04 | 1300 | 4096 | 4096 | 4096 (0)|
| 3 | TABLE ACCESS FULL | T2 | 1 | 76285 | 76285 |00:00:00.13 | 1300 | | | |
----------------------------------------------------------------------------------------------------------------------

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

1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=5)
 2 - filter(ROW_NUMBER() OVER ( ORDER BY "OWNER","OBJECT_NAME")<=5)
22 rows selected.

Elapsed: 00:00:00.06
<pre>

Cioè nel mio caso oracle non si aspetta 5 righe ma tutte le 76285 presenti nella tabella, nonostante il fatto che sia scritto nella query che il risultato conterrà 5 righe. Perché a me non funziona come dovrebbe quindi non è ancora chiaro, ho provato a ricalcolare statistiche a cambiare client (oltre che server) ma non ho visto miglioramenti, un tema da indagare.

P.S.

Attenzione che sulla funzionalità FETCH..OFFSET è gia stato rilevato un baco, se ne parla qui, io ho effettuato lo stesso test riportato da Connor Mcdonald nel primo commento con lo stesso risultato.

 

 

 

Standby database per Oracle standard edition 11gR2

mercoledì 15 gennaio 2014 alle 15:36 | Pubblicato su 11g, Installation and Configuration | Lascia un commento
Tag: , ,

Sono passati oltre quatto anni da quando scrissi questo post in cui parlai dell’implementazione del sistema di disaster recovery basato sullo standby database su Oracle standard edition. Qualche tempo fa mi è stato chiesto se eravamo in grado di mettere in piedi questa soluzione, siccome però sono passati gli anni  però, ora la nostra versione di riferimento è oracle 11.2 e non più 10.2 con la quale feci i test a suo tempo. C’è da dire che a suo tempo ho anche messo in piedi una implementazione completa, con tutta la gestione automatizzata del trasferimento degli archived log e della loro applicazione sullo standby database su una installazione con Oracle 9.2.

Con un po’ di pazienza sono riuscito a crearmi un ambiente virtualizzato (con virtual box, che per questi test sembra funzionare molto bene). Ho creato quindi una macchina virtuale con Oracle Linux 6.3 64 bit, vi ho installato Oracle Database 11.2.0.3. A questo punto ho clonato la macchina e in qualche modo ho sistemato il nome e l’indirizzo IP. Ho creato un database sulla prima macchina, poi ho seguito i miei appunti usati a suo tempo per Oracle 9.2 per creare lo standby database e fare qualche prova: il risultato è che funziona tutto allo stesso modo in cui funzionava su Oracle 9.2 e Oracle 10.2. L’unico inghippo l’ho riscontrato quando ho fatto un test che forse a suo tempo non avevo fatto: l’aggiunta di una nuova tablespace con relativo database; in questo caso mi sono imbattuto nel problema ben descritto qui, così ho scoperto l’esistenza del parametro STANDBY_FILE_MANAGEMENT. Per rendermi la vita facile quello che ho fatto è stato di modificare il parametro e ricreare da zero lo standby database.

Ieri sono riuscito a fare un ulteriore test, il cui esito al momento pare positivo, cioè applicare l’aggiornamento alla versione 11.2.0.4.  Mi sono trovato un po’ spiazzato con questo aggiornamento, per due motivi: il primo è che non ho trovato al suo interno le solite istruzioni (ho trovato la guida “Upgrade” fra la documentazione ufficiale ma questa, a voler essere pignoli, si riferisce alla versione 11.2.0.3; il secondo motivo di spiazzamento è che fare l’aggiornamento “in-place” è stato reso complicato da Oracle. Ho trovato comunque lo spazio per fare l’aggiornamento “out-of-place” come richiesto, quindi creando una nuova Oracle Home. Alla fine della parte di aggiornamento della parte “software” l’installer lancia automaticamente DB Upgrade Assistant (DBUA) che nonostante i miei timori ha eseguito la parte di aggiornamento del database senza errori.

Il bello però viene nell’aggiornamento dello standby database. La mia idea era quella di aggiornare il software e sperare che la sincronizzazione tramite l’applicazione degli archived logs funzionasse aggiornando anche lo standby database. Ciò che è accaduto è che lanciando anche sullo standby l’installer di 11.2.0.4 è andato tutto bene fino alla parte di aggiornamento del software, poi è partito DBUA il quale però manco trovava le informazioni sul database da aggiornare, in quanto in effetti non aveva le informazioni registrate sul file /etc/oratab. Poco male, anzi stavo per aggiungerle quando mi sono reso conto che comunque DBUA non avrebbe potuto fare nulla perché lo standby database non è apribile in scrittura (se non con una switch-over) . Io qui ho interrotto la procedura ed ho provveduto manualmente ad applicare gli archived logs generati sul primary e tutto pare aver funzionato bene, ho fatto nuovi test e pare funzionare come atteso (l’unica cosa che non ho detto è che ho copiato il contenuto della directory “dbs” dalla vecchia alla nuova Oracle Home.

Prossimamente conto  di fare lo stesso test con Oracle 12.1

Oracle 12c: Multitenant architecture e pluggable database, parte II

lunedì 25 novembre 2013 alle 25:49 | Pubblicato su 12c | Lascia un commento

Devo fare qualche aggiunta e precisazione al mio post precedente sull’argomento. Recentemente ho fatto ulteriori test, su una macchina virtuale, soprattutto per verificare una cosa che ho notato guardando il documento sulle licenze ho notato che si dice l’architettura multitenant con un solo “pluggable database” è disponibile in tutte le edizioni, quindi anche con la Standard Edition. Chiaramente può sembrare poco utile, ma secondo me invece qualche utilità può averla, infatti io posso creare un PDB sul mio database server in locale, staccarlo e riattaccarlo su un altro database server (purché in modalità Multitenant), quindi un’ulteriore modalità di trasporto dati.

Un’altra cosa che avevo dimenticato di scrivere sull’altro post, perché effettivamente non è citata dalla documentazione, è che “in teoria” le operazioni di creazione, attacco (plug-in) e stacco (unplug) di un PDB possono essere fatte dal “Database Configuration Assistant (DBCA), ho scritto però in teoria, perché mentre sulla creazione non ho avuto problemi, ne ho avuti nell’operazione di stacco, problemi che invece non ho avuto a fare tutte le operazioni da SQL*Plus, come da indicazioni sul capitolo 38 dell'”Administrators Guide“. Da SQL*Plus sono riuscito senza problemi e in tempi abbastanza rapidi a creare un nuovo PDB, a staccarlo, a dropparlo (su una standard edition, dove ne posso avere uno solo alla volta) e a riattaccarlo. Nel fare quest’ultima operazione mi sono scordato di cambiare il nome copiando il comando dal manuale, ho così visto che quando si attacca un PDB gli si può dare un nuovo nome.

 

Oracle 12c: Multitenant architecture e pluggable database

venerdì 23 agosto 2013 alle 23:40 | Pubblicato su 12c | 5 commenti
Tag: ,

Come probabilmente i più attenti e interessati sanno bene dal primo luglio 2013 è ufficialmente stata rilasciata la versione 12c (release 1) del database Oracle. In realtà, per la precisione, il pacchetto software per Linux è diventato disponibile gia qualche giorno prima, uno dei primi ad annunciarlo è stato Tanel Poder. In quei giorni molti dei blog specialistici che più o meno cerco di seguire hanno ripreso vita e pubblicato post sulle nuove caratteristiche della nuova versione, che è stata sottoposta a un programma di beta testing da parte di molti di questi blogger che sono specialisti ed esperti di database Oracle. Io non ho seguito inizialmente con molto entusiasmo questo nuovo rilascio, anche perché sono ancora alle prese con installazioni Oracle 10gR1 e solo da poco abbiamo escluso finalmente la possibilità di fare nuove installazioni 10gR2 prendendo finalmente come versione di riferimento la 11gR2. Avendo però avuto un po’ di tempo libero a disposizione ho deciso di investirlo per indagare sulle nuove caratteristiche e funzionalità introdotte da Oracle nella nuova versione del database, in modo da non trovarmi più avanti spiazzato.

La caratteristica più enfatizzata e dai più ritenuta interressante è la cosiddetta architettura “multitenant” e i “pluggable database”. Ho dato una letta al capitolo 17 del manuale Concepts dove viene fatta una introduzione quasi commerciale ai vantaggi di questa nuova architettura che permette di facilitare in sostanza il cosiddetto consolidamento rendendo più facile portare su un’unico database server più database, ottimizzando quindi l’utilizzo delle risorse harware e riducendo l’attività di manutenzione. Come è fatta questa architettura? Il concetto, a grandi linee è che c’è un database server, del tutto analogo a un database server pre-12c, con datafile, control file, online redo log, undo, sga ecc che però alla creazione viene definito come “container”, questo viene definito CDB. Piccola nota: sulla documentazione Oracle la terminologia viene usata in modo leggermente diverso, in particolar modo nella definizione di container, questo però mi confonde ancora un pochino, quindi mi prendo la libertà di reinterpretare tale nomenclatura in modo leggermente diverso. Probabilmente Oracle con il termine “container” designa” un contenitore di dati, mentre io avrei pensato a un contenitore di altri database, cosa che oracle chiama “multitenant container database (CDB)”.

Un CDB in effetti è del tutto analogo a un database classico Oracle, però ci si possono attaccare dei “Pluggable Database (PDB)” che in realtà sono una collezione di schemi con i relativi datafile e tempfile. L’undo, come il redo e l’istanza è gestita dal CDB. Il PDB si porta dietro anche un catalogo (tablespace SYSTEM) che, credo, (devo ancora approfondire) contenga il catalogo relativo al solo PDB, cataloghi relativi a feature come Spatial (per dirne uno che mi viene in mente) con lo schema MDSYS credo sia contenuto, gestito e condiviso dal CDB.

Un CDB contiene almeno almeno due “container” (secondo la terminologia Oracle), uno chiamato PDB$ROOT o semplicemente root che contiene i metadati comuni a tutti e impropriamente credo possa essere usato anche come database Oracle normale e un “seed PDB”, chiamato PDB$SEED, che è un template per creare nuovi PDB all’interno del CDB. Possono essere creati/attaccati fino a 253 PDB in un CDB. Fin qui si parla di una sorta di nuovo livello di astrazione, la cosa importante e forse più interessante è che i PDB sono PDB appunto perché possono essere “staccati” e “attaccati”  (unplugged & plugged) fra diversi CDB. Un PDB a livello fisico è un insieme di datafile e un file XML che è il descrittore del PDB, tramite questo XML si può attaccare il PDB su un nuovo CDB in modo abbastanza semplice. Queste operazioni possono essere fatte da “Cloud Control”, (che io non ho ancora visto) o da SQL*Plus. Un PDB può essere creato da zero partendo quindi dal PDB$SEED oppure clonando un’altro PDB, cosa questa che pare interessante.

Questo tipo di architettura in prospettiva è sicuramente molto interessante, guardando al presente o al massimo al futuro prossimo o alla realtà in cui lavoro io devo dire che per me è di scarsa utilità. Prima di tutto  dove lavoro io ci sono si diversi database che potrebbero essere consolidati, c’è un solo problema: sono ancora su versioni diverse, 9iR2 (ormai a esaurimento per fortuna) 10gR2 e 11gR2. Passare alla nuova archiettura multitenant significa anche migrare la versione, quindi è una cosa fattibile solo in alcuni anni, molto gradualmente (per fare un esempio, un nostro grosso cliente sta migrando ora da Oracle 10gR1 a 11gR2…). Un altra cosa da non sottovalutare è che questa caratteristica è un’opzione dell’Enterprise Edition, non ho idea di quanto costi, ma sicuramente non è alla portata di tutti, richiedendo appunto EE. E’ anche vero che questa pare essere proprio una caratteristica/funzionalità “Enterprise” :)

Un database comunque può essere creato non-CDB, quindi sarà del tutto analogo a un classico database oracle come lo abbiamo finora conosciuto fino alla versione 11, non è possibile passare da un database non-CDB a uno CDB e viceversa.

Dopo aver letto il capitolo 17 del manuale “Concepts”, si può passare ad approfondire con la lettura del manuale “Administrator’s Guide, a partire dal capitolo 36.

Concludo con un solo piccolo accenno alla interfaccia di amministrazione del database fornita di default, chiamata ora “Enterprise Manager Express”, implementata direttamente nel database tramite XDB, quindi non più esternamente tramite OC4J come in precedenza, questo significa ad esempio che se il DB è giu non risponde neanche la console. Graficamente sembra un po’ più moderna e “cool” più compatto, ma mi pare con molte meno funzionalità, ad esempio non trovo l’interfaccia per lo scheduler, immagino sia stato demandato al “Cloud Control” ma devo indagare. In ogni caso qualche problemino c’è, ne ha parlato anche Dizwell.

P.S.

naturalmente prima di poterne parlare non ho solo letto i manuali ma ho anche provato a installare la nuova versione e creato un nuovo database su una macchina con Oracle Linux 5 64 bit.

Inghippi con il Character Set – Conclusione

giovedì 1 agosto 2013 alle 01:23 | Pubblicato su 11g, Diario, SQL, Varie | Lascia un commento
Tag:

Un titolo decisamente ottimista per un post su questo argomento, la mia speranza è comunque di chiudere l’argomento ripreso non molto tempo fa con il post “Inghippi con il Charcter SET“.  L’ispirazione mi è venuta leggendo la nota del supporto Oracle

NLS_LANG Explained (How does Client-Server Character Conversion Work?) (Doc ID 158577.1)

che a sua volta mi ha rimandato alla nota:

The correct NLS_LANG in a Microsoft Windows Environment (Doc ID 179133.1)

Entrambe le note precisano che per gestire in modo corretto il character set è meglio utilizzare SQL Developer, però danno anche altri spunti interessanti. Ad esempio viene specificato:

The “Unicode” “chcp 65001″ and “chcp 65000″ values are NOT supported with sqlplus.exe.

Poi usano un character set che forse non avevo mai notato: WE8PC850 che pare andare molto d’accordo con il CP 850 settato di default sulle macchine Windows.

Sempre adottando i corretti settaggi ho verificato che si può aggirare i limiti di sqlplus adottando comandi registrati su file e poi invocandoli da sqlplus tramite il comando START, bisogna però fare attenzione alla codifica del file su cui si salvano i comandi, ecco  un esempio:

C:\tmp>chcp 65001
Tabella codici attiva: 65001

C:\tmp>set NLS_LANG=.AL32UTF8

C:\tmp>more insert_test_charset.sql
Memoria insufficiente.

C:\tmp>SQLPLUs sviluppo50/sviluppo50@svil112_methone

SQL*Plus: Release 11.2.0.3.0 Production on Thu Aug 1 13:17:23 2013

Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – 64bit Production
With the Partitioning, Data Mining and Real Application Testing options
PL/SQL procedure successfully completed.
Session altered.

SVILUPPO50@svil112_methone > delete from test_charset;

8 rows deleted.

SVILUPPO50@svil112_methone > @insert_test_charset.sql

1 row created.
1 row created.

SVILUPPO50@svil112_methone > SELECT * FROM TEST_CHARSET;

A
—————————————————————————————————-
KKKKà
NNNè

SVILUPPO50@svil112_methone >

Il file è formato utf-8 (senza il famigerato BOM) e si noti come il comando more fallisca con il messaggio “memoria insufficente”

Il contenuto del file insert_test_charset.sql è:

INSERT INTO TEST_CHARSET VALUES (‘KKKKà’);
insert into test_charset values (‘NNNè’);

In realtà poi, lavorando con caratteri compresi nella codifica West-Europe, usare UTF-8 lato client nel mio caso è superfluo, credo che d’ora in poi userò WE8PC850

Ancora Character Set, ORA-00600 [kafspa:columnBuffer2]

giovedì 1 agosto 2013 alle 01:55 | Pubblicato su 11g, Diario, Installation and Configuration, Varie | Lascia un commento
Tag: , ,

Non c’è dubbio che la gestione del Character Set sui database Oracle sia una cosa tutt’altro che banale e poco chiara ai più. Ieri controllando i log di un database interno utilizzato per i test ho trovato il seguente errore:

ORA-00600: internal error code, arguments: [ORA-00600: internal error code, arguments: [kafspa:columnBuffer2], [4053], [4000], [], [], [], [], []

Il database è un 10.2.0.5 su linux 64 bit, recentemente migrato da una vecchia macchina dove c’era però una versione 10.2.0.3. Ho passato i dati dal vecchio database al nuovo tramite expdp/impdp dei vari schemi (approfittando per fare un po’ di pulizia). L’errore veniva generato durante il calcolo delle statistiche notturno e nell’alert.log c’era rimando a un file di trace su cui ho trovato anche dettagli sulla tabella che provocava l’errore. Il secondo e terzo argomento dell’errore ORA-00600 mi ha fatto subito sospettare il tipo di problema (che fra l’altro in forme diverse ho gia incontrato altre volte. In effetti ho individuato nella tabella un campo definito come VARCHAR2(4000) facendo una query simile a questa:


SELECT NOMECAMPO FROM NOMETABELLA WHERE LENGTH(NOMECAMPO)>4000

ottenevo sempre l’errore  ORA-00600.

Facendo una ricerca sul supporto Oracle ho trovato poco, facendone una Google sono arrivato qui, come dire: a volte ritornano. Infatti in coda al post che non ricordavo di aver gia letto ho trovato dei miei commenti. Avendo anche cambiato il titolo del blog non mi ricordavo neanche chi fosse l’autrice :)

In realtà ho scoperto con un po’ di sorpresa che lo schema proveniva in effetti da un dump fornitoci dal cliente, che però io credevo avesse database con character set UTF-8 solo di recente sono riuscito a scoprire che in realtà il cliente utilizza charset ISO8859-15 e che quindi ero incappato sullo stesso problema. Il bello è che per trovare una soluzione, dopo alcuni banali tentativi per isolare i record con stringhe lunghe più di 4000 byte all’interno del campo incriminato, ho provato a fare un export con data pump e importare la tabella su un’altro schema dello stesso database, con una certa sorpresa mi sono trovato sul nuovo schema una copia della tabella con lo stesso problema.

Dopo vari esperimenti, alla fine, sfruttando la chiave primaria della tabella, che è un id generato da sequence,  ho isolato un record con il problema; in realtà ho trovato anche altri 6 record che su un campo varchar2(600) avevano stringhe che occupavano ben più di 600 byte ma questi record creavano problemi solo nei tentativi di CREATE TABLE AS …

In teoria ho risolto facendo un update sul campo per chiave:


UPDATE NOMETABELLA SET NOMECAMPO=SUBSTR(NOMECAMPO,1,4000) WHERE CAMPOCHIAVE=XXX

che con un certo mio sconcerto ha funzionato (apparentemente), in seguito ho fatto alcune prove, compreso il ricalcolo delle statistiche, senza riscontrare problemi, stamattina però nell’alert.log ho ritrovato l’errore sulla stessa tabella, in realtà mi aspettavo di trovare l’errore sulla copia che ho mantenuto con l’errore per fare ulteriori verifiche è così è stato anche se in un primo momento non era chiaro guardando il trace.

Stamattina ho avuto modo di fare ricerche più approfondite e mirate sul problema, leggendo nota del supporto Oracle intitolata:

“Changing the NLS_CHARACTERSET From AL32UTF8 / UTF8 (Unicode) to another NLS_CHARACTERSET (Doc ID 1283764.1)”

al paragrafo 1.d ho trovato la seguente frase:

Do NOT use Expdp/Impdp when going from (AL32)UTF8 to a single byte NLS_CHARACTERSET on ALL 10g versions lower then 10.2.0.4 (including 10.1.0.5). Also 11.1.0.6 is affected.
It will provoke data corruption unless Patch 5874989 is applied on the Impdp side. Expdp is not affected, hence the data in the dump file is correct.Also the “old” exp/imp tools are not affected.
This problem is fixed in the 10.2.0.4 and 11.1.0.7 patch set.
Fixed in 11.2.0.1 and up

 

che mi ha un po’ illuminato. In realtà ho dovuto un po’ ricostruire la storia. Sul nostro nuovo database di test 10.2.0.5 (che dovrebbe essere esente dal bug) ho due schemi dello stesso cliente, uno importato direttamente dal dump fornito dal cliente e su cui non si presenta il problema, infatti nei log dell’import trovo:

ORA-02374: conversion error loading table “SCHEMA2″.”NOMETABELLA”
ORA-12899: value too large for column NOMECAMPO (actual: 3995, maximum: 4000)
ORA-02372: data for row:

L’altro schema, sui ho trovato il problema, proveniva dallo stesso dump, ma era passato prima dal vecchio database 10.2.0.3, quindi era stato importato sul vecchio db, dove si era generata la corruzione (senza che io me ne accorgessi), poi da li è stato esportato  e importato sul nuovo database, senza errori nei log di data pump. Mi pare quindi che Oracle abbia corretto parzialmente il problema, perché impdp non genera più la corruzione sulla tabella ma scarta i dati in importazione, però, se la tabella è gia corrotta essa viene esportata e importata da datapump tale e quale, corruzione compresa. Prossimamente conto di provare a fare dei test su un Oracle 11.2.0.3, magari se ne trovo uno con character set ISO8859 posso fare dei test più completi.

Riguardo la gestione del character set su Oracle riporto qui un paio di riferimenti a note Oracle che vale la pena leggere:

  • AL32UTF8 / UTF8 (Unicode) Database Character Set Implications (Doc ID 788156.1)
  • Changing the NLS_CHARACTERSET From AL32UTF8 / UTF8 (Unicode) to another NLS_CHARACTERSET (Doc ID 1283764.1)
  • NLS_LANG Explained (How does Client-Server Character Conversion Work?) (Doc ID 158577.1)

Inghippi con il Character SET

venerdì 25 gennaio 2013 alle 25:19 | Pubblicato su Diario | 3 commenti
Tag:

Tanto tempo fa ho dedicato un paio di post alla gestione della “globalizzazione” in Oracle, i post sono questo  e questo. Ad oggi ogni tanto ancora incontro problemi nella gestione sul database di caratteri particolari quali le lettere accentate utilizzate con tastiere italiane, tipo la “à”. Oggi ho fatto un piccolo approfondimento, devo però prima fare una premessa. Come client Oracle io utilizzo prevalentemente SQL*Plus, sul mio PC ho installato l’instant client con SQL*Plus, riducendo così al minimo il software installato. L’instant client ha il vantaggi di essere “portabile”, come si dice oggi, basta copiare il pacchetto su un pc, settare le opportune variabili d’ambiente e tutto funziona. Occasionalmente utilizzo anche SQL Developer dove l’interfaccia grafica mi è utile.

Normalmente i database su cui lavoro hanno come charset principale AL32UTF8 il che significa che il database non ha certo problemi a registrare tutti i caratteri che si possono trovare su una tastiera italiana, anzi potrebbe memorizzare correttamente anche caratteri da altri alfabeti più esotici contemporaneamente, a questo serve l’UTF8.

Premesso ciò mi sembra che se si utilizza SQL Developer non ci siano grossi problemi, SQL Developer pare gestire  (almeno sulla mia installazione) le lettere accentate senza problemi; con SQL*Plus invece ci sono grossi problemi ogni qual volta si vuole gestire caratteri non ascii, quali ad esempio la “à”. Come avevo indicato nei due vecchi post succitati in teoria è possibile impostare sulle finestre dos di windows il charset UTF8 (con il comando CHCP 65001 e impostando i font “Lucida Console”), poi settando opportunamente la variabile NLS_LANG=.AL32UTF8 . In teoria, perché io in pratica non ci sono riuscito, sul mio pc con Windows 7 semplicemente non funziona e io le lettere accentate contenute in campi Varchar2 di un mio database non le vedo correttamente.


C:\tmp>set NLS_LANG=.AL32UTF8

C:\tmp>sqlplus sviluppo50/sviluppo50@svil112_methone

SQL*Plus: Release 11.2.0.3.0 Production on Fri Jan 25 10:05:25 2013

Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Data Mining and Real Application Testing options
PL/SQL procedure successfully completed.
Session altered.

SVILUPPO50@svil112_methone > select * from test_charset;

A
---------------------------------------------------------------------------------------
��
��

&nbsp;
SVILUPPO50@svil112_methone > SELECT * FROM NLS_DATABASE_PARAMETERS
 2 WHERE PARAMETER LIKE 'NLS_CHARACTERSET';

PARAMETER VALUE
------------------- -------------------
NLS_CHARACTERSET AL32UTF8

 

Mi è stato possibile collegandomi con putty a un server linux, settando su putty il charset utf-8 e settando la variabile NLS_LANG, ma non da sqlplus invocato da windows. Lasciando la situazione di default (quindi con codepage 850):


C:\tmp>chcp 850
Tabella codici attiva: 850

C:\tmp>set NLS_LANG=

C:\tmp>sqlplus sviluppo50/sviluppo50@svil112_methone

SQL*Plus: Release 11.2.0.3.0 Production on Fri Jan 25 10:11:20 2013

Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Data Mining and Real Application Testing options
PL/SQL procedure successfully completed.
Session altered.

SVILUPPO50@svil112_methone > select * from test_charset;

A
--------------------------------------------------------------------------------
a
a

Alla fine l’unico compromesso che ho trovato per risolvere il mio problema è stato di adottare sul client il charset cp1252, quindi settando chcp 1252 e NLS_LANG=.WE8MSWIN1252 effettivamente riesco a leggere e inserire la ‘à’


C:\tmp>chcp 1252
Tabella codici attiva: 1252

C:\tmp>set NLS_LANG=.WE8MSWIN1252

C:\tmp>sqlplus sviluppo50/sviluppo50@svil112_methone

SQL*Plus: Release 11.2.0.3.0 Production on Fri Jan 25 10:13:19 2013

Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Data Mining and Real Application Testing options
PL/SQL procedure successfully completed.
Session altered.

SVILUPPO50@svil112_methone > select * from test_charset;

A
--------------------------------------------------------------------------------
à
à

SVILUPPO50@svil112_methone > update test_charset set a='è';

2 rows updated.

SVILUPPO50@svil112_methone > select * from test_charset;

A
--------------------------------------------------------------------------------
è
è

Non voglio tediare ulteriormente, ma usando chcp 65001 e NLS_LANG=AL32UTF8 cercado di fare update con lettere accentate sqlplus si sloggga, provare per credere.

Pagina successiva »

Crea un sito o un blog gratuitamente presso WordPress.com. | The Pool Theme.
Entries e commenti feeds.

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.

Unisciti agli altri 71 follower