2015-09-23 19 views
5

utilizza la funzione TO_CHAR al numero di formato da 0001 a 9999, e per adattarsi alla dimensione di colonna (VARCHAR2(4)) in cui è inserito il valore (anche se il valore è> 9999).Oracle numero formato to_char con modalità di riempimento (FM0000)

a utilizzare la funzione in questo modo:

TO_CHAR(n, 'FM0000') 

Esempi che funzionano:

SELECT TO_CHAR(1, 'FM0000') FROM DUAL; 

Risultato: 0001

SELECT TO_CHAR(1234, 'FM0000') FROM DUAL; 

Risultato: 1234

Ma quando provo con un valore superiore a 9999, ottengo un carattere aggiuntivo:

SELECT TO_CHAR(12345, 'FM0000') FROM DUAL; 

Risultato: #####

SELECT TO_CHAR(123456, 'FM0000') FROM DUAL; 

Risultato: #####

Per informazioni, il risultato che mi aspettavo era #### (su 4 caratteri).

Riassumendo:

  • Quando il valore da convertire corrisponde alla dimensione prevista (4), il valore convertito ha la stessa lunghezza (4)
  • Quando il valore da convertire è più lungo la dimensione prevista (5 o più), il valore convertito ha un carattere in più della lunghezza prevista (5).

Come spiegarlo?

non ho trovato spiegazione nella documentazione di Oracle qui https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm#i170559

ho provato su diverse versioni di Oracle (9, 10, 11) ed il risultato è lo stesso.

La soluzione che ho trovato è quello di troncare il risultato con RPAD function() RPAD(TO_CHAR(n,'FM0000'), 4), ma ho bisogno di capire il motivo per cui la funzione TO_CHAR non è sufficiente.

+2

'SELEZIONA TO_CHAR (-1, 'FM0000') FROM DUAL;' –

+1

Che cosa esattamente si cercando di ottenere? Quale valore si desidera restituire se si seleziona un numero maggiore di 9999 (ad esempio 12345)? – Ollie

+1

Se si esegue la query con <= 4 cifre in SQL \ * Plus, si noterà che l'intestazione della colonna viene sempre visualizzata con cinque caratteri, 'TO_CH'. Deve comunque tenere conto del segno del valore, oltre alle quattro cifre significative che si desidera. (Come la domanda di Florin mostra ...). Si potrebbe anche provare con ''FMS000'' per vederlo esplicitamente per valori positivi. Potresti usare 'substr (to_char (...), -4)' come soluzione alternativa. –

risposta

9

Il modello di formato deve ancora consentire il segno del valore. Non c'è modo di indicare a TO_CHAR() che non può mai essere negativo (se questo è il caso dei tuoi valori). Anche con un numero di 4 cifre consente la formattazione permette di cinque caratteri, come si può vedere dalla colonna:

SQL> SELECT TO_CHAR(1234, 'FM0000') FROM DUAL; 

TO_CH 
----- 
1234 

Avviso di colonna è TO_CH, che è di cinque caratteri, non quattro.Se si dispone di un numero negativo (come suggerito Florin) è necessario che lo spazio in più:

SQL> SELECT TO_CHAR(-1234, 'FM0000') FROM DUAL; 

TO_CH 
----- 
-1234 

Senza il FM modificatore si ottiene uno spazio di primo piano nella stringa restituita per i valori positivi, in modo LENGTH(TO_CHAR(1234, '0000')) è 5 ma LENGTH(TO_CHAR(1234, 'FM0000')) è 4, perché lo spazio iniziale (che normalmente rende giustificati i valori nella colonna) viene soppresso. Con un valore negativo, la lunghezza della stringa restituita è 5 in entrambi i casi. Il modello di formato determina che il tipo di dati restituito è varchar2(5) a consentire per il segno, anche se si sa che non ci saranno mai valori negativi - non c'è alcun modo per il modello di formato di riflettere tale.

Si può vedere con i valori positivi anche se si forza il segno possa essere indicato:

SQL> SELECT TO_CHAR(1234, 'FMS0000') FROM DUAL; 

TO_CH 
----- 
+1234 

Non c'è niente che si può fare al riguardo nella chiamata TO_CHAR. Come alternativa al vostro RPAD soluzione alternativa, è possibile utilizzare SUBSTR per ottenere solo gli ultimi quattro caratteri della stringa formattata:

SQL> SELECT SUBSTR(TO_CHAR(12345, 'FM0000'), -4) FROM DUAL 

SUBSTR(TO_CHAR(1 
---------------- 
#### 

Ma se si hanno valori negativi che ci si perde il segno:

SQL> SELECT SUBSTR(TO_CHAR(-1234, 'FM0000'), -4) FROM DUAL 

SUBSTR(TO_CHAR(- 
---------------- 
1234 

Con il vostro RPAD si mantiene il segno, ma perdono la quarta cifra significativa:

SQL> SELECT RPAD(TO_CHAR(-1234, 'FM0000'), 4) FROM DUAL 

RPAD(TO_CHAR(-12 
---------------- 
-123 

che non è anche buono. Potresti non avere a che fare con numeri negativi; ma se hai a che fare con un numero maggiore di quello che ti aspetti (cioè ottieni un numero> = 10000 quando ti aspetti solo < = 9999) allora non sono sicuro che tu possa essere certo di non vedere un (invalido?) numero negativo ad un certo punto. Questo sembra essere un problema di dati piuttosto che un problema di formattazione, ad un certo livello comunque.


Basato sul tuo commento e Ollie, un altro approccio che potrebbe essere più esplicito ed evidente ai futuri manutentori del codice è di precisare che in un caso:

SELECT CASE WHEN n BETWEEN 0 AND 9999 THEN TO_CHAR(n, 'FM0000') ELSE '####' END FROM DUAL 

il che permetterà anche lasciare la colonna di stringhe null o usare qualche altro valore magico invece di ####, se lo si desidera.

E un altro modo per tagliare il valore, che può anche essere più chiaro, è con CAST:

SQL> SELECT CAST(TO_CHAR(12345, 'FM0000') AS VARCHAR2(4)) FROM DUAL; 

CAST 
---- 
#### 
Problemi correlati