Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
823 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Un besoin de date ...

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Un besoin de date ...

n°1672035
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 11:53:56  profilanswer
 

Bonjour,

 

J'ai un problème incompréhensible  :sarcastic: Je pose les bases ...

 

SGBD : SQL Server 2000
Contraintes : J'ai une table qui contient une date dans un champ de type VARCHAR. Cette contrainte n'est pas négociable... sinon il n'y aurait probablement pas de problèmes...
Le bug:  Lors d'une simple comparaison de dates sur ce champs je me prend une belle exception. cf le script ci dessous

Code :
  1. CREATE TABLE [TMP_DATE_TEST] (
  2.    [Id] [int] IDENTITY (1, 1) NOT NULL ,
  3.    [prc_date] [varchar] (80) COLLATE French_CI_AS NULL    
  4. ) ON [PRIMARY]
  5. GO
  6.  
  7. INSERT INTO TMP_DATE_TEST VALUES ('01/01/2008')
  8. INSERT INTO TMP_DATE_TEST VALUES ('22801')
  9. INSERT INTO TMP_DATE_TEST VALUES ('02/02/2008')
  10. INSERT INTO TMP_DATE_TEST VALUES ('03/03/2008')
  11. INSERT INTO TMP_DATE_TEST VALUES ('04/04/2008')
  12.  
  13. SELECT *
  14. FROM TMP_DATE_TEST
  15. WHERE ISDATE(prc_date) = 0
  16.  
  17. -- ----------------------
  18. -- |Id    |prc_date    |
  19. -- ----------------------
  20. -- |2    |22801        |
  21. -- ----------------------
  22.  
  23. SELECT *
  24. FROM TMP_DATE_TEST
  25. WHERE ISDATE(prc_date) = 1
  26.  
  27. -- ----------------------
  28. -- |Id    |prc_date    |
  29. -- ----------------------
  30. -- |1    |01/01/2008    |
  31. -- ----------------------
  32. -- |3    |02/02/2008    |
  33. -- ----------------------
  34. -- |4    |03/03/2008    |
  35. -- ----------------------
  36. -- |5    |04/04/2008    |
  37. -- ----------------------
  38.  
  39. SELECT *
  40. FROM TMP_DATE_TEST
  41. WHERE isdate(prc_date) = 1
  42. AND CAST(prc_date AS datetime) < CAST('03/03/2008' AS datetime)
  43.  
  44. SELECT *
  45. FROM TMP_DATE_TEST
  46. WHERE isdate(prc_date) = 1
  47. AND CONVERT(datetime, prc_date) < CONVERT(datetime,'03/03/2008')
  48.  
  49. DROP TABLE TMP_DATE_TEST
  50. GO
 

Regardez attentivement ce script, et si quelqu'un comprend pourquoi ces requettes ne fontionne pas....

 
Code :
  1. SELECT *
  2. FROM TMP_DATE_TEST
  3. WHERE isdate(prc_date) = 1
  4. AND CAST(prc_date AS datetime) < CAST('03/03/2008' AS datetime)
  5. -- WHY ?????
  6. -- Serveur : Msg 241, Niveau 16, État 1, Ligne 1
  7. -- Erreur de syntaxe lors de la conversion d'une valeur datetime à partir d'une chaîne de caractères.
  8.  
  9. SELECT *
  10. FROM TMP_DATE_TEST
  11. WHERE isdate(prc_date) = 1
  12. AND CONVERT(datetime, prc_date) < CONVERT(datetime,'03/03/2008')
  13. -- WHY ?????
  14. -- Serveur : Msg 241, Niveau 16, État 1, Ligne 1
  15. -- Erreur de syntaxe lors de la conversion d'une valeur datetime à partir d'une chaîne de caractères.
 

Merci d'avance :)


Message édité par Koyomi le 16-01-2008 à 11:54:26
mood
Publicité
Posté le 16-01-2008 à 11:53:56  profilanswer
 

n°1672056
MagicBuzz
Posté le 16-01-2008 à 12:07:47  profilanswer
 

1/ Juste une petite remarque à propos des conversions de dates : le format que tu utilises est indifférenciable syntaxiquement du type américain. Pour cette raison, afin de réduire les risques d'erreur de conversion, utilise toujours le 3° paramètre de CONVERT (et n'utilise pas CAST) afin de forcer le pattern de la date.
 
2/ A vérifier dans la doc de SQL Server, mais à mon avis, il n'y a RIEN qui impose l'ordre d'exécution des conditions SQL. Du coup, le "isdate()" est certainement dans ton cas évalué après tes tentatives de conversion. Je te conseille donc de passer par un IF :
 

Code :
  1. SELECT *
  2. FROM tmp_date_test
  3. WHERE 0 = IF isdate(prc_date) then IF CONVERT(datetime, prc_date) < CONVERT(datetime,'03/03/2008') then 0 else 1 end else 1 end


(ouais, c'est un peu barbare, mais ça devrait éventuellement corriger ton problème)
 
Si tu veux un truc moins barbare, tu peux faire une sous-requête qui fitre déjà les dates valides, et tu fais tes tests sur ce résultat.

n°1672064
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 12:10:50  profilanswer
 

Merci de ton eclaircisement ^^
 
J'aurai jurer que l'ordre des executions des condition etait effectif sur sql server. (foutu a priori :sarcastic:)
 
Je vais potasser tout cela merci ;)

n°1672075
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 12:18:35  profilanswer
 

A partir de tes conseils, je suis parti sur cela :

Code :
  1. SELECT T1.*
  2. FROM (SELECT * FROM TMP_DATE_TEST WHERE isdate(prc_date) = 1) T1
  3. WHERE CONVERT(datetime, T1.prc_date) < CONVERT(datetime,'03/03/2008')


 
-> Même erreur :S, le problème est que je ne peut spécifier le dernier paramètre de CONVERT car dans la realité j'ai ce type de valeur : 01/02/2008 ou 01/02/08 ...
 
J'ai également essayer cela (ta proposition) :

Code :
  1. SELECT *
  2.    FROM tmp_date_test
  3.    WHERE 0 =     IF isdate(prc_date) then
  4.             IF CONVERT(datetime, prc_date) < CONVERT(datetime,'03/03/2008') then 0
  5.             else 1
  6.             end
  7.         else 1
  8.         end


 
et la j'obtient une erreur. Je ne connaisait pas cette syntaxe donc je vais creuser un peu

n°1672088
MagicBuzz
Posté le 16-01-2008 à 12:24:44  profilanswer
 

je vais faire quelques tests, je te tiens au courant.
 
mais là t'es bien parti pour avoir besoin d'une PS.

n°1672096
MagicBuzz
Posté le 16-01-2008 à 12:28:22  profilanswer
 

C'est marrant ton truc :D
 

Code :
  1. SELECT t1.*, case when CONVERT(datetime, T1.prc_date) < CONVERT(datetime,'03/03/2008') then 1 else 0 end grmpf
  2. FROM (SELECT * FROM TMP_DATE_TEST WHERE isdate(prc_date) = 1) T1


Ca plante pas [:magicbuzz]


Message édité par MagicBuzz le 16-01-2008 à 12:32:08
n°1672101
MagicBuzz
Posté le 16-01-2008 à 12:31:36  profilanswer
 

Mais ça ça plante : [:cerveau heink]  

Code :
  1. select * from
  2. (
  3. SELECT t1.*, case when CONVERT(datetime, T1.prc_date) < CONVERT(datetime,'03/03/2008') then 1 else 0 end grmpf
  4. FROM (SELECT * FROM TMP_DATE_TEST WHERE isdate(prc_date) = 1) T1
  5. ) t2
  6. where grmpf = 1


 
j'ai l'impression que l'optimiseur réécrit complètement la requête à chaque fois, et se met à faire n'importe quoi là où on tente de lui faire suivre une certainement logique.
 
à mon avis, tu vas donc devoir passer par une vue afin d'empêcher l'optimiseur de faire n'importe quoi :

Code :
  1. CREATE VIEW grmpf
  2. AS
  3. SELECT id, prc_date
  4. FROM tmp_date_test
  5. WHERE isdate(prc_date) = 1
  6. go


 
Ensuite tu fais ta requête tu début, mais sur la vue :

Code :
  1. SELECT *
  2. FROM grmpf
  3. WHERE isdate(prc_date) = 1
  4. AND CONVERT(datetime, prc_date) < CONVERT(datetime,'03/03/2008')


 
arf, non, ça marche pas [:magicbuzz]
 
amuse-toi bien, là c'est total n'importe quoi ce que fait SQL Server...
 
t'es bon pour faire une fonction qui retourne une table (comme la vue, mais une fonction, là t'es sûr que SQL Server va pas s'amuser à faire n'importe quoi... enfin... sûr... espérer tout du moins :D


Message édité par MagicBuzz le 16-01-2008 à 12:37:57
n°1672114
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 12:46:00  profilanswer
 

ca me rassure j'avais peur d'etre le seul a croire que Sql Serv se vautrait sur le coup ^^

n°1672119
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 12:49:00  profilanswer
 

Le seule solution que j'ai trouvée pour l'instant :
 

Code :
  1. SELECT *
  2. FROM TMP_DATE_TEST
  3. WHERE [id] IN (SELECT [id] FROM TMP_DATE_TEST WHERE isdate(prc_date) = 1)
  4. ANDprc_date < '03/03/2008'

n°1672130
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 12:54:13  profilanswer
 

Encore plus fort ...
 

Code :
  1. SELECT * FROM TMP_DATE_TEST WHERE [id] IN (
  2. SELECT [id] FROM TMP_DATE_TEST WHERE isdate(prc_date) = 1)
  3. --and prc_date < '03/03/2008' -> OK
  4. --and convert(datetime, prc_date) < '03/03/2008' -> KO
  5. --and prc_date < convert(datetime, '03/03/2008') -> KO

mood
Publicité
Posté le 16-01-2008 à 12:54:13  profilanswer
 

n°1672135
MagicBuzz
Posté le 16-01-2008 à 12:58:41  profilanswer
 

le souci, c'est que si tu passes pas par des dates, :
 
10/01/1900 > 01/01/2008
 
:/

n°1672140
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 13:07:16  profilanswer
 

Oui :'(
 
J'arrive pas a croire que je vais devoir faire un immondice pour un truc aussi idiot ...

n°1672145
Koyomi
www.sebastiengilles.com
Posté le 16-01-2008 à 13:12:56  profilanswer
 

Bon j'ai trouvé une solution porchesque :D
 

Code :
  1. SELECT *
  2. INTO #tmp_date_test
  3. FROM TMP_DATE_TEST
  4. WHERE ISDATE(prc_date) = 1
  5.  
  6. SELECT *
  7. FROM #tmp_date_test
  8. WHERE convert(datetime, prc_date) < convert(datetime, '03/03/2008')


 
TADAAAA !!!!!

n°1672196
MagicBuzz
Posté le 16-01-2008 à 14:18:36  profilanswer
 

en effet :jap:


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Un besoin de date ...

 

Sujets relatifs
Date 2008-01-09 vers Mercredi 9 janvier 2008 ?Convertir date anglaise en francaise
Compteur de visite journaliére, fonctions de date en sqlFenetre, comparaison, resultat... besoin d'aide (bis)
Fenetre, comparaison, resultat... besoin d'aideBesoin d'aide pour un DM svp...
besoin d'aide pour page avec player Besoin d'aide pour programmation page d'Inscription
[C++] [résolu] Besoin d'un coup de main pour déboguer mon algo de tribesoin d'aide date php
Plus de sujets relatifs à : Un besoin de date ...


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR