Archivi tag: oracle

oracle-ecommerce-integration

Oracle e LOB

di Andrea Tassotti

Non me ne vorranno i colleghi di questo blog che per lavoro o diletto praticano il mondo della programmazione Java, ma nello storico contenzioso tra sistemista e programmatore (contenzioso su risorse e sicurezza) si osserva una (dico) “perversa” tendenza tutta (ahimé) dei programmatori Java nel prediligere l’uso di campi LOB di tipo BLOB o CLOB (raramente NCLOB) per risolvere questioni di memorizzazione di informazioni non strettamente primitive, con particolare propensione alla serializzazione di oggetti o immagazzinamento di file di ogni sorta (e orrore, anche xml, trascurando il tipo nativo Oracle) [a difesa dei colleghi del blog…molte volte si ereditano scelte progettuali che sarebbero devastanti da cambiare] in questo tipo di campi, con buona pace o la connivenza [close your eyes] di tanti DBA.
Continua a leggere

Oracle RMAN – Creazione e configurazione di un recovery database

di Andrea Tassotti

Introduzione

Oracle DB

Un RMAN Recovery Catalog è uno schema di database che mantiene dei metadati dettaglianti le operazioni per il backup eseguite da RMAN su un database obiettivo. I metadati includono le seguenti informazioni riguardo il database gestito: struttura, configurazione RMAN, i backup dei datafile e degli archive log (backup sets, pieces e copie), i redo logs archiviati e le loro copie. Continua a leggere

Guida alle date in Oracle

oracle db

Innanzitutto chiariamo un fatto troppo spesso equivocato: Oracle RDBMS, come qualsivoglia software, gestisce le informazioni sul tempo in forma numerica (rappresentazione interna), tipicamente considerando un spiazzamento da un punto temporale prefissato e stabilendo una unita di misura, avvalendosi oppure no del segno e dunque fissando il riferimento dello 0. Ma questi sono “internals” che riguardano gli sviluppatori in casa Redwood.

La struttura di memoria per conservare l’informazione varia dai 7 agli 11 bytes secondo il tipo di dato (fisso a 7 per le date, variabile per intervalli e timestamp), pertanto siamo tra 256 e 288 di possibili valori per la unita di misura minima considerata (secondi nel caso di date, frazioni di millesimi di secondo negli altri casi), ossia valori ragguardevoli.

Ma veniamo alla rappresentazione esterna di queste informazioni.

Per rappresentazione esterna intendiamo le forme in cui l’utente esprime questi valori e come il motore li presenti allo stesso utente (il meccanismo ha una certa reciprocità)

Dobbiamo considerare che l’interfaccia utente è mediata dal linguaggio SQL: questo non è un fatto marginale.
Come ogni linguaggio artificiale dobbiamo considerare simboli terminali e le varie forme di composizione, fino all’apporto fornito da “funzioni”.

Il linguaggio SQL implementato in Oracle concepisce i valori temporali come “letterali”, ossia come simboli terminali: pertanto riconosce una data come cosa differente da un char. Allo stesso modo, benché non ne introduca letterali, saprà riconoscere la diversità semantica da un valore numerico (e quindi gli operatori applicabili) per tutto ciò che è timestamp o intervalli.

Cosa vogliamo dire?
Semplicemente che esiste una sintassi, un formato con cui esprimere o in cui vengono espressi valori temporali. In particolare un formato per esprimere date.
Questo risente ovviamente della localizzazione geografica dell’interfaccia in quanto la data (più che il tempo) si esprime in modi diversi nelle varie culture.

Entrano in gioco in questo caso due variabili server (che possono essere reimpostate in sessione): NLS_DATE_FORMAT o NLS_TERRITORY
La prima consente di impostare la rappresentazione delle date esplicitamente, la seconda come conseguenza della localizzazione di tutte le informazioni che lo prevedano (date, valute, ecc)

Nell’ipotesi di un motore configurato per la lingua italiana, la stringa formata da due cifre per giorno, tre lettere per la forma abbreviata del mese e due cifre per l’anno (senza il secolo) e divise da un separatore (‘-‘ per sqlplus, ‘/’ per sqldeveloper grazie appunto a modifiche nella sessione di collegamento) rappresenta una data:

21-SET-12

Questa è la forma che otteniamo leggendo colonne di tipo data, ma se quotata, questa è anche la forma naturalecon cui impostare il valore in una colonna di tipo data:

INSERT INTO DATARIO VALUES ('21-SET-12')

Se impostiamo NLS_DATE_FORMAT in un altro modo, allora tutto potrà essere fatto con forme (ad esempio) anglosassoni per le date (nei nomi, e nella disposizione delle componenti).

Ma esistono alcuni problemi: un problema (se così li vogliamo considerare) è mostrare la completezza dell’informazione: le colonne di tipo data mantengono informazione sul secolo, sull’orario fino ai secondi, ma nessuna di queste viene mostrata nel formato standard impostato da NLS_DATE_FORMAT.Un altro problema nasce considerando il fatto che non sempre le informazioni pervengono al motore SQL nel formato utile, e tantomeno è utile estrarre dati in questo formato in quei contesti in cui occorre una maggiore attenzione alla forma (in documenti, report, interfacce utente finale, ecc).

Ed è in questi casi che entrano in gioco le funzioni SQL per la conversione (tra tipi di dati): TO_CHAR e TO_DATE.

Facciamo due esempi:

  • nel primo esempio cerchiamo di estrarre l’informazione sull’orario da una colonna di tipo data
  • nel secondo consideriamo l’ipotesi di trasformare in formato utente (o esterno) in data e una data in formato utente, ed è naturale che il tipo per lo scambio con il mondo esterno sia il più malleabile VARCHAR.

Per il primo problema usiamo la funzione TO_CHAR.
Questa converte un tipo dati (tra quelli definiti nel suo campo di azione) in una rappresentazione a caratteri attraverso una maschera di formato definita da utente e passata come argomento assieme al dato da convertire.
Abbiamo:

Formato interno -> TO_CHAR -> Formato utente specificato

Per questo esempio sfruttiamo un’altra funzione, SYSDATE, che restituisce un tipo data e viene quindi visualizzzato attraverso quanto stabilito da NLS_DATE_FORMAT. Ma attraverso la funzione TO_CHAR provvediamo a mostrare anche le componenti assenti nell’altra visualizzazione:

SELECT TO_CHAR(SYSDATE, 'MM-DD-YYYY HH24:MI:SS') "NOW" FROM DUAL;

Per il secondo problema utilizzeremo entrambe le funzioni TO_CHAR e TO_DATE e creeremo una tabella di esempio:

CREATE TABLE anag (
cod NUMBER(4),
nome VARCHAR2(20),
data_ass DATE);

In particolare la funzione TO_DATE converte una stringa che esprime una data in un tipo data. Al fine di far comprendere all’interprete SQL la data specificata occorre indicare anche il suo formato.

Formato utente -> TO_DATE -> Formato interno

Inseriamo dei dati in diversi formati utente:

INSERT INTO anag VALUES(1, 'Rossi', TO_DATE('10/01/1999', 'dd/mm/yyyy'));
INSERT INTO anag VALUES(2, 'Verdi', TO_DATE('12/02/06', 'dd/mm/yy'));
INSERT INTO anag VALUES(3, 'Gialli', TO_DATE('20100815', 'yyyymmdd'));
INSERT INTO anag VALUES(4, 'Blu', TO_DATE('101-2005', 'ddd-yyyy'));
SELECT nome, TO_CHAR(data_ass, 'dd.mm.yy') FROM anag;
SELECT nome, TO_CHAR(data_ass, 'dd-month-yy') FROM anag;
SELECT nome, TO_CHAR(data_ass, 'dd day month-yyyy') FROM anag;

Possiamo infine concludere con due osservazioni:

 

  • non è necessario utilizzare TO_DATE per impostate una data; è sufficiente essere conformi al formato dettato da NLS_DATE_FORMAT
  • se proprio occorre una conversione, e la si considera necessaria per tutte le query (in senso assoluto), è possibile reimpostare NLS_DATE_FORMAT secondo esigenze, almento a livello di sessione

 

Si imposta il formato data (nella sessione) con:

ALTER SESSION SET nls_date_format='dd.mm.yy';

Per tutti gli altri casi: usate TO_CHAR e TO_DATE a volontà.

oracle-ecommerce-integration

Velenosissimi problemi di startup

Oracle quando ci si mette fa diventare pazzi di rabbia; ho provato ad avviare una istanza che sapevo configurata (ometto per il momento alcuni passaggi per non rovinarvi la sorpresa):

SQL> startup
ORA-27103: internal error
Linux-x86_64 Error: 2: No such file or directory
Additional information: 101

Ovviamente cerco dettagli su alert.log e altre possibili fonti, compreso il documento ufficiale per gli errori (b14219.pdf, che per errore 27103 mi suggerisce di chiamare l’assistenza!!!!).

Internet neanche a parlarne: tanti errori e (im)probabili soluzioni, ma neanche una traccia di questo errore.

Non vi dico le peripezie e il percorso con cui sono venuto a soluzione. Anche il caso ci ha messo del suo.

In ogni modo devo prima svelarvi il contesto omesso precedentemente: l’istanza risiede in un virtual environment di un container OpenVZ (tecnologia di zoning per Linux).

L’ambiente è stato creato clonando una macchina fisica (su cui l’istanza girava correttamente): la clonazione è avvenuta con la semplice copia del filesystem con un TAR, omettendo quei percorsi legati al kernel sorgente che avrebbero potuto collidere con il kernel della macchina virtualizzatrice (/proc, /dev, /sys, ecc). Tecnica sperimentata in precedenza decine di volte con successo, anche con istanza Oracle presenti.

Ed è stato proprio in /dev il problema: nella ricostruzione di tutti gli i-node standard presenti in questo percorso mi sono dimenticato (e poi fortunosamente ricordato cercando di usarlo nel contesto di un comando che stavo eseguendo per altre configurazioni) del file speciale /dev/zero.

In assenza di questo file Oracle va in pappa e genera l’errore indicato all’inizio, senza altra informazione.

Buon Oracle a tutti

Oracle: Note operative sul FLASHBACK

oracle dbNote operative sul Flashback in oracle.

Testato con: Oracle 10g – 11g

Per poter utilizzare le tecnologia di Flashback è necessario che il vostro db sia opportunamente configurato

Ecco alcune delle principali funzionalità fornite dalla tecnologia Flashback

  • FLASHBACK TO BEFORE DROP -> riporta la tabella allo stato antecedente al drop:
DROP TABLE table_name;
...
SHOW RECYCLEBIN
...
FLASHBACK TABLE table_name to BEFORE DROP;

Continua a leggere

Cercare il nome di una colonna all’interno dell’intero db [Update: 29/03/12]

oracle db

Aggiornato al 29/03/12, grazie alle segnalazioni di Andrea 😉

Problema: verificare l’esistenza di una determinata colonna all’interno del db inserendo il suo nome o parte di esso

Testato: oracle db, 10g – 11g

Soluzione: eseguire il seguente comando sql sostituendo a nomecolonna il nome della colonna (o parte di esso) da ricercare:

  • Utente amministratore
select table_name, column_name from all_tab_columns
where column_name like '%nomecolonna%'
  • Utente generico
select table_name, column_name from USER_TAB_COLUMNS
where column_name like '%nomecolonna%'