2010-01-07 8 views
1

Étant donné que cela semble plus d'une question de syntaxe, ma recherche n'a donné aucun résultat utile.Oracle TO_DATE ne conserve pas le format

Je tente d'effectuer une requête qui obtient des données européennes à partir d'une base de données américaine en utilisant l'heure GMT. J'ai besoin d'avoir l'heure européenne, mais je n'arrive pas à la faire fonctionner correctement.

permet de dire "myDateField" = '01 -01 à 2010'

SELECT TO_CHAR(myDateField + (60/1440), 'Mon" "DD", "YYYY') 

produit exactement ce que je veux, mais je en ai besoin de rester comme une date.
Produit: '1 janvier 2010'

SELECT TO_DATE(TO_CHAR(myDateField + (60/1440)), 'Mon" "DD", "YYYY') 

Mérites un "pas un mois valide" erreur.
Produit: Erreur

SELECT TO_DATE(TO_CHAR(myDateField + (60/1440), 'Mon" "DD", "YYYY'), 'Mon" "DD", "YYYY') 

Works, mais la mise en forme est perdue.
Produit: « 01-01-2010 »

Comment puis-je formater ce que je puisse obtenir le résultat de la première déclaration donne, mais aussi garder comme une date? Ou y a-t-il une meilleure méthode?

EDIT:
Tout comme un exemple de cette requête particulière travaillant dans une situation différente ... Ceci est la même requête, mais au lieu de convertir en temps européenne, il se transforme en un autre fuseau horaire en Amérique du Nord.

SELECT TO_DATE(TO_CHAR(NEW_TIME(myDateField, 'GMT', 'MDT')), 'Mon" "DD", "YYYY') 

Produit exactement ce que je veux, tout en conservant les données sous forme de date.
Produit: '1 janvier 2010'

En résumé:

Est-il possible de prendre "myDateField + (60/1440)", ou utiliser le "FROM_TZ" les mots-clés, et faire le résultat utiliser le format "Mon" "DD", "YYYY", tout en conservant son type Date?

+0

commentaire sur votre « En résumé »: Non - c'est, votre client peut choisir un moyen de formatage des valeurs DATETIME, comme Dan a fait remarquer. Mais c'est juste la façon locale de l'outil pour représenter la date. Cela ne change pas la valeur réelle des données. L'utilisation de TO_CHAR change la valeur: elle sérialise la date en une chaîne au format spécifié. Vous pouvez réorganiser la chaîne et l'interpréter comme DATE, mais le résultat sera à nouveau une valeur de date sans mise en forme inhérente. Le format ne fait tout simplement pas partie du type de données ou des valeurs qu'il régit. –

+0

Merci. Je suppose que je vis juste dans les nuages ​​... Juste pour une question rapide, pourquoi TO_DATE (myDateField + (60/1440), 'Mon "" DD "," YYYY') produisent un "mois non valide" " Erreur? (Vous semblez être très instructif sur le sujet) – Sivvy

Répondre

2

Nouvelle réponse, depuis la première la confusion adressé ce jour vs char, pas les fuseaux horaires.

Vous avez demandé s'il y a une meilleure façon. Je pense qu'il y a: utiliser le support de fuseau horaire Oracle.

voir: http://download.oracle.com/docs/cd/B19306_01/server.102/b14225/ch4datetime.htm#i1006333

Exemple requête pour convertir un datetime à un autre fuseau horaire:

SELECT FROM_TZ(
     CAST(TO_DATE('1999-12-01 11:00:00','YYYY-MM-DD HH:MI:SS') AS TIMESTAMP) 
     , 'America/New_York' 
     ) 
     AT TIME ZONE 'America/Los_Angeles' "West Coast Time" 
FROM DUAL; 

L'utilisation de ces fonctions assurent que le calcul est correct. Après cela, vous pouvez le format de cours comme vous le souhaitez, par exemple:

SELECT TO_CHAR(
     FROM_TZ(
      CAST(TO_DATE('1999-12-01 11:00:00','YYYY-MM-DD HH:MI:SS') AS TIMESTAMP) 
     , 'America/New_York' 
     ) 
     AT TIME ZONE 'America/Los_Angeles' 
     , 'MON DD, YYYY') "West Coast Time" 
FROM DUAL; 

... mais comme je l'ai dit dans la première réponse, le résultat ici sera un CHAR, pas une date.

+0

Le plus drôle, c'est que je jouais avec ça avant de poster. Cela ne me permet pas de le formater comme je l'avais espéré. Désolé de paraître difficile. – Sivvy

+0

J'ai ajouté un résumé à ma question, si cela vous aide. – Sivvy

+1

J'ai ajouté un exemple de formatage de la façon que vous avez spécifiée. La raison pour laquelle je vous conseille d'utiliser les constructions FROM_TZ et AT TIME ZONE est qu'elles garantissent que les maths sont bien faites. Le calcul du fuseau horaire n'est pas trivial, et vous devriez utiliser l'installation intégrée si elle est là. Le formatage est une question de présentation. Vous reformateriez seulement pour afficher ou exporter la date - pas si vous voulez l'insérer dans la base de données. –

4

Je pense qu'il est important de réaliser que la mise en forme que vous désirez prend effet dans le cadre de la conversion de DATE à CHAR types. Donc, votre exigence, "définir le format mais le garder comme date" n'a pas de sens - pas dans Oracle ce n'est pas le cas.

Si vous voulez juste ajouter un intervalle de temps à une date et garder une date, c'est tout ce qui est nécessaire:

myDateCol + (60/1440) -- add one hour to the date 

et si vous voulez formater que dans le style européen, il devient

TO_CHAR(myDateCol + (60/1440), 'MON DD, YYYY') 

mais bien sûr, il sera alors chaîne, une représentation lisible de la valeur de date réelle. Et à cause du format, cela manque réellement l'information de temps.

Vous pouvez convertir de cours cette date Toa arrière:

TO_DATE(TO_CHAR(myDateCol + (60/1440), 'MON DD, YYYY'), 'MON DD, YYYY') 

mais sérieusement - il n'y a pas de point - parce que la partie de temps n'est pas présent dans la chaîne, cette date aura réellement 00:00:00 comme le temps. Donc vous venez de perdre des informations.

Cela devient clair quand vous faites des choses comme ceci:

TO_CHAR(myDateCol + (60/1440), 'MON DD, YYYY HH24:MI:SS') 

comparer cela aussi:

TO_CHAR(
    TO_DATE(
    TO_CHAR(myDateCol + (60/1440), 'MON DD, YYYY HH24:MI:SS') 
    , 'MON DD, YYYY' 
) 
, 'MON DD, YYYY HH24:MI:SS' 
) 

(la dernière exprression montre comment tronqués les fiels temps)

+0

Merci pour le conseil ... Dans ce cas particulier, le temps n'est pas nécessaire.Merci pour la perspicacité cependant, et je vais mettre à jour la question avec une requête que j'ai qui fonctionne correctement sous une instance similaire, à la seule exception étant qu'il utilise "NEW_TIME" au lieu de l'expression (60/1440). – Sivvy

3

Une date est juste une date - il n'a pas de format de chaîne intrinsèque. Il s'agit d'un format par défaut, c'est-à-dire lorsque vous interrogez une date dans un programme ou une bibliothèque qui l'extrait sous la forme d'une chaîne, il existe un paramètre par défaut quant à la façon dont il sera formaté.

Une approche consiste à simplement interroger la date et votre format de programme client il. Par exemple, en Java, vous pouvez utiliser la classe DateFormat.

Mais vous pouvez aussi essayer ALTER SESSION SET NLS_DATE_FORMAT = 'Mon dd, yyyy'

et qui pourrait fonctionner.

Edit: Votre deuxième requête a retourné une erreur not a valid month pour moi. Avez-vous exécuté cela après avoir suivi ma suggestion ALTER SESSION?

+0

La chaîne de requête est utilisée dans un autre programme (SAP Business Objects) ... En formatant la date dans la chaîne de requête, cela signifie que les utilisateurs n'ont pas besoin de la formater à chaque fois qu'ils l'utilisent. – Sivvy

+0

Retournez ensuite une valeur CHAR, pas une date. – Dan

+0

Voilà comment je l'ai actuellement. Le problème est qu'ils ne peuvent pas utiliser la plupart des fonctionnalités fournies lors de l'utilisation des dates. C'est pourquoi je dois revenir en arrière et le changer à une date, mais ne peux pas comprendre comment l'obtenir correctement. – Sivvy

Questions connexes