Brico-Info - le blog de Bruno CATTEAU

Aller au contenu | Aller au menu | Aller à la recherche

jeudi 21 décembre 2006

Problème de date dans une base de données

Une autre problématique dès que l'on travaille sur plusieurs bases (Access, Sql Server, Oracle) et que l'on est confronté à des langues différentes au niveau des serveurs... Même le LCID = 1036 (qui permet d'imposer la langue utilisée par le serveur web) ne vient pas à bout de certaines architectures ! En plus la syntaxe SQL de la langue n'est pas identique selon les bases. Donc pour éviter de voir le 7 mai se transformer en 5 juillet, voilà une solution, l'utilisation du format ODBC compatible avec les trois bases citées :

L'idée est de transformer un format de date jj/mm/aaaa ou mm/dd/yyyy en un format identique : {d 'aaaa-mm-jj} {d 'yyyy-mm-dd} ou un format comportant les heures : {ts 'yyyy-mm-dd hh:mm:ss'} ou {ts 'aaaa-mm-jj hh:mm:ss'}

La requête SQL devient  "... WHERE champ > {d '2006-08-23} "


'****************************************************************************************************
' Fonction     : strODBCDate
' Objet        : Preparer l'insertion d'une date dans une requete SQL
' Entrée       :
'               - dtmParam : date a traiter
' Retour       : chaine a inserer directement dans le code SQL
' Sortie       :
' Commentaires : le format final est {d 'aaaa-mm-jj'}
'                quelle que soit la langue d'installation de la base cible
' Exemple      :
'****************************************************************************************************
Function strODBCDate(ByVal dtmParam)
 Dim strOut
 If IsNull(dtmParam) Or dtmParam="" Then
  strOut = Null
 Else
  If Not IsDate(dtmParam) Then
   strOut = Null
  Else
   Dim strMonth, strDay
   Dim dtmMonth, dtmDay
   ' Traitement du mois si sur un seul chiffre
   dtmMonth = Month(dtmParam)
   If dtmMonth<10 Then
    strMonth = "0" & CStr(dtmMonth)
   Else
    strMonth = CStr(dtmMonth)
   End If
   ' Traitement du jour si sur un seul chiffre
   dtmDay = Day(dtmParam)
   If dtmDay<10 Then
    strDay = "0" & CStr(dtmDay)
   Else
    strDay = CStr(dtmDay)
   End If
   ' Creation de la chaine de retour
   strOut = "{d '" & CStr(Year(dtmParam)) & "-" & strMonth & "-" & strDay & "'}"
  End If
 End If
 strODBCDate = strOut
End Function


'=======================================================================================
' Fonction     : strODBCDateTime
' Objet        : Preparer l'insertion d'une date dans une requete SQL
' Entrée       :
'               - dtmParam : date et heure a traiter
' Retour       : chaine a inserer directement dans le code SQL
' Sortie       :
' Commentaires : le format final est {ts 'aaaa-mm-jj hh:mm:ss'}
'                quelle que soit la langue d'installation de la base cible
' Exemple      :
'=======================================================================================
Function strODBCDateTime(ByVal dtmParam)
 Dim strOut
 If IsNull(dtmParam) Or dtmParam="" Then
  strOut = Null
 Else
  If Not IsDate(dtmParam) Then
   strOut = Null
  Else
   Dim strMonth, strDay
   Dim dtmMonth, dtmDay
   Dim strHour, strMinutes, strSecondes
   strHour =hour(dtmParam)
   strMinutes= minute(dtmParam)
   strSecondes = second(dtmParam)
   ' Traitement du mois si sur un seul chiffre
   dtmMonth = Month(dtmParam)
   If dtmMonth<10 Then
    strMonth = "0" & CStr(dtmMonth)
   Else
    strMonth = CStr(dtmMonth)
   End If
   ' Traitement du jour si sur un seul chiffre
   dtmDay = Day(dtmParam)
   If dtmDay<10 Then
    strDay = "0" & CStr(dtmDay)
   Else
    strDay = CStr(dtmDay)
   End If
   If strHour<10 Then
    strHour = "0" & CStr(strHour)
   Else
    strHour = CStr(strHour)
   End If
   If strMinutes<10 Then
    strMinutes = "0" & CStr(strMinutes)
   Else
    strMinutes = CStr(strMinutes)
   End If
   If strSecondes<10 Then
    strSecondes = "0" & CStr(strSecondes)
   Else
    strSecondes = CStr(strSecondes)
   End If
   ' Creation de la chaine de retour
   strOut = "{ts '" & CStr(Year(dtmParam)) & "-" & strMonth & "-" & strDay & " "& strHour & ":"& strMinutes & ":"& strSecondes&"'}"
  End If
 End If
 strODBCDateTime = strOut
End Function 


 

dimanche 10 décembre 2006

Recherche "Case insensitive", "Accent insensitive" multi-base

Pour faire une recherche "Case insensitive" et "Accent insensitive", plusieurs solutions :

  • Configurer la table de la base "CIAI" et chaque requete sera  "Case Insensitive" et "Accent Insensitive"
  • Transformer le mot recherché pour parametrer la requetes SQL permettant de comparer des choses comparables...

Sous ORACLE :

SELECT * from table WHERE TRANSLATE (UPPER(champ4), 'ÉÈÊÀÁÂÄÇÌÍÎÏÑÓÒÔÖÚÙÛÜ', 'EEEAAAACIIIINOOOOUUUU') LIKE TRANSLATE (UPPER('%réunion  commerciale%'), 'ÉÈÊÀÁÂÄÇÌÍÎÏÑÓÒÔÖÚÙÛÜ', 'EEEAAAACIIIINOOOOUUUU')
Cette syntaxe permet de comparer des chaines en majuscule dont les caractères accentués ont été remplacé par des caractères non accentués...).

Sous Oracle, il y a une autre solution (merci Cédric Courlet)

UPPER(CONVERT(VAR_SEARCHSTRING, 'US7ASCII'))

Sous SQL Server et Access :

SELECT * from table WHERE champ4 like '%r[eéèêë][uúùûü][nñ][iìíîï][oóòôö]n%'
Dans ce cas, on voit que le SQL gère une forme de syntaxe d'expression régulière alors que sous ORACLE, on a du procéder à un remplacement.

Dans ces deux cas, on a accès à une recherche riche puisque "réunion commerciale" ressort les éléments suivants :

  • En majuscule sans accent : REUNION COMMERCIALE
  • En minuscule sans accents : reunion commerciale
  • En majuscule avec accent : RÉUNION COMMERCIALE
  • En minuscule sans accent : réunion commerciale

Tout quoi !

Concaténation : Compatibilité inter-base

Le caractère permettant de concaténer deux champs dans une requête sont différents sous Access, Sql Server et Oracle !

  • Pour MS Access ce sera "&"
  • Pour MS Sql Server "+"
  • Pour Oracle "||"

Exemple :

SELECT champ1 & champ2 FROM table WHERE clause
SELECT champ1 + champ2 FROM table WHERE clause
SELECT champ1 || champ2 FROM table WHERE clause

Allez comprendre !