Un besoin de date ...

Un besoin de date ... - SQL/NoSQL - Programmation

Marsh Posté le 16-01-2008 à 11:53:56    

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
Reply

Marsh Posté le 16-01-2008 à 11:53:56   

Reply

Marsh Posté le 16-01-2008 à 12:07:47    

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.

Reply

Marsh Posté le 16-01-2008 à 12:10:50    

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 ;)

Reply

Marsh Posté le 16-01-2008 à 12:18:35    

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

Reply

Marsh Posté le 16-01-2008 à 12:24:44    

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

Reply

Marsh Posté le 16-01-2008 à 12:28:22    

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
Reply

Marsh Posté le 16-01-2008 à 12:31:36    

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
Reply

Marsh Posté le 16-01-2008 à 12:46:00    

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

Reply

Marsh Posté le 16-01-2008 à 12:49:00    

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'

Reply

Marsh Posté le 16-01-2008 à 12:54:13    

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

Reply

Marsh Posté le 16-01-2008 à 12:54:13   

Reply

Marsh Posté le 16-01-2008 à 12:58:41    

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

Reply

Marsh Posté le 16-01-2008 à 13:07:16    

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

Reply

Marsh Posté le 16-01-2008 à 13:12:56    

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 !!!!!

Reply

Marsh Posté le 16-01-2008 à 14:18:36    

en effet :jap:

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed