2015-11-13 2 views
3

je dois select des données de base de données Oracle 11g, mais je ne peux pas à comprendre pourquoi la suite select requête échoue:Les résultats de la conversion de la date SQL en "paramètre de modèle de format numérique non valide".

SELECT 
    INFO_ID, 
    INFO_DETAIL, 
    IMPORTANT_FLG, 
    DELETE_FLG, 
    CREATE_TIME, 
    DISPLAY_ORDER 
    FROM TABLE_NAME 
    WHERE TO_DATE(TO_CHAR(CREATE_TIME, 'YYYY/MM/DD'), 'YYYY/MM/DD') 
    BETWEEN TO_DATE(TO_CHAR(:fromDate, 'YYYY/MM/DD'), 'YYYY/MM/DD') AND TO_DATE(TO_CHAR(:toDate, 'YYYY/MM/DD'), 'YYYY/MM/DD') 
    ORDER BY IMPORTANT_FLG DESC NULLS LAST , DISPLAY_ORDER ASC NULLS LAST, CREATE_TIME DESC, INFO_ID ASC 

La requête échoue avec message d'erreur suivant:

ORA-01481: invalid number format model 
01481. 00000 - "invalid number format model" 
*Cause: The user is attempting to either convert a number to a string 
     via TO_CHAR or a string to a number via TO_NUMBER and has 
     supplied an invalid number format model parameter. 

Mon entrée pour les variables fromDate et toDate sont juste des chaînes de date telles que 20111010 etc. J'ai aussi essayé plus de temps spécifique (même format que dans le tableau), mais cela ne semble pas être le problème ..

Dans la base de données de la colonne CREATE_TIME est de type TIMESTAMP(6), et par exemple un échantillon est 2011/12/19 08:04:42

Toutes les idées pourquoi cela erreur apparaît?

+0

Je ne connais pas PL/SQL (tel qu'utilisé par Oracle) mais vous devriez pouvoir utiliser ISO-8601 ("aaaa-MM-jj") comme format. Avez-vous essayé d'utiliser des tirets au lieu de barres obliques? – Dai

+0

@dai, merci pour la suggestion. Malheureusement je reçois la même erreur même avec des tirets (j'ai essayé: sans tirets en entrée, avec des tirets en entrée, et aussi des tirets pour le paramètre TO_CHAR) – julumme

+0

'TO_CHAR (: fromDate, 'AAAA/MM/DD')' est faux. Vous convertissez un NUMBER en STRING, en supposant qu'il s'agit de DATE. '20111010' n'est pas une DATE, c'est un NUMBER. De plus, "20111010" n'est pas une DATE, c'est une STRING. Ils sont complètement différents. –

Répondre

5

Racine Cause:

Vous convertissez un NUMÉRO à STRING, en supposant qu'il soit DATE. 20111010 n'est pas une DATE, c'est un NUMÉRO. En outre, '20111010' n'est pas une date, c'est une chaîne. Ils sont complètement différents.

  • 20111010 - NUMÉRO
  • '20111010' - STRING
  • TO_DATE('20111010','YYYYMMDD') - DATE

Erreur:

SQL> SELECT TO_CHAR(20111010, 'YYYY/MM/DD') FROM dual; 
SELECT TO_CHAR(20111010, 'YYYY/MM/DD') FROM dual 
         * 
ERROR at line 1: 
ORA-01481: invalid number format model 

En venant à votre requête:

WHERE TO_DATE(TO_CHAR(CREATE_TIME, 'YYYY/MM/DD'), 'YYYY/MM/DD') 
    BETWEEN TO_DATE(TO_CHAR(:fromDate, 'YYYY/MM/DD'), 'YYYY/MM/DD') 
AND TO_DATE(TO_CHAR(:toDate, 'YYYY/MM/DD'), 'YYYY/MM/DD') 

Vous compliquez inutilement la conversion et la mise en forme.

Le TIMESTAMP est une extension datatype sur la DATE datatype. En plus des éléments datetime de la DATE type de données, le timestamp détient une fraction de seconde à une précision entre 0 et 9 décimales, la valeur par défaut étant 6.

In the database the CREATE_TIME column is TIMESTAMP(6) type, and for example one sample is 2011/12/19 08:04:42

Puisque vous avez affaire à TIMESTAMP vous pourrait utiliser TO_TIMESTAMP.

Tout en faisant une DATE/timestamp arithmétique, vous devez laisser le type de données tel qu'il est et ne pas le convertir en chaîne.Vous devez utiliser TO_CHAR uniquement pour afficher.

Modifier votre prédicat filtre:

WHERE CREATE_TIME 
BETWEEN TO_TIMESTAMP(:fromDate, 'YYYY/MM/DD') 
AND TO_TIMESTAMP(:toDate, 'YYYY/MM/DD') 

Au-dessus, :fromDate et :toDate doit être une chaîne et non un numéro .

Par exemple,

SQL> SELECT to_timestamp('20111010', 'YYYYMMDD') FROM dual; 

TO_TIMESTAMP('20111010','YYYYMMDD') 
----------------------------------------------------------- 
10-OCT-11 12.00.00.000000000 AM 

Ou, utilisez TO_CHAR d'abord convertir le numéro dans chaîne:

SQL> SELECT to_timestamp(TO_CHAR(20111010), 'YYYYMMDD') FROM dual; 

TO_TIMESTAMP(TO_CHAR(20111010),'YYYYMMDD') 
------------------------------------------------------------------ 
10-OCT-11 12.00.00.000000000 AM 
+0

Cela m'a appris plusieurs choses tout en résolvant le problème. Il devrait être possible de voter deux fois;) – julumme

3

J'espère que cette solution aide.

Il y a trop de conversions inutiles.

J'ai simulé le même scénario dans mon système, enter image description here

Ici CREATED_TIME est une colonne de type de données timestamp(6).

+0

Merci pour votre réponse, vous avez raison! – julumme

+0

@Jeethu .. Où est la réponse ici? –

+0

@LalitKumarB il pourrait ne pas être la réponse pour vous. Mais je l'ai guidé dans la bonne direction. Réponse est trop simple, ne faites pas de choses inutiles dans SQL, gardez les choses simples. Aussi, vous avez fourni la réponse, si ma réponse était fausse, le PO n'aurait jamais commenté ma réponse est correcte. – Jeethu