sql >> Database teknologi >  >> RDS >> Sqlserver

Sammenligning af datoer gemt som varchar

At gemme datoværdier som varchar er simpelthen forkert.

Hvis det er muligt, bør du ændre tabellen for at gemme dem som datodatatype.
Du kan gøre det med nogle få enkle trin:

  1. Omdøb de nuværende kolonner (jeg gætter på, at ScheduleStartDate også er varchar) til columnName_old. Dette kan nemt gøres ved at bruge sp_rename .

  2. Brug alter table for at tilføje kolonnerne med den relevante datatype.

  3. Kopiér værdierne fra de gamle kolonner til de nye kolonner ved hjælp af en opdateringssætning. Da alle datoer er gemt i samme format, kan du bruge convert sådan:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103) Hvis din sql-serverversion er 2012 eller nyere, skal du bruge try_convert . Bemærk, at jeg har brugt nullif , ltrim og rtrim at konvertere værdier, der kun indeholder mellemrum, til null.
  4. Slip og genskab indekser, der refererer til disse kolonner. Den nemmeste måde at gøre dette på er ved at højreklikke på indekset på SSMS og vælge script index as -> drop and create .
  5. Brug alter table for at fjerne de gamle kolonner.

Bemærk: hvis der refereres til disse kolonner i andre objekter i databasen, skal du også ændre disse objekter. Dette inkluderer lagrede procedurer, fremmednøgler osv.

Hvis du ikke kan ændre datatyperne af kolonnerne, og din sql-serverversion er lavere end 2012, skal du bruge konverter som denne:

SELECT * FROM tblServiceUsersSchedule 
WHERE CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103) 
      < CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL

Bemærk, at hvis du har en enkelt række, hvor kolonnens data ikke er i formatet dd/MM/åååå, vil dette give en fejl.

For sql-serverversioner 2012 eller nyere, brug Try_convert . Denne funktion vil simpelthen returnere null, hvis konverteringen mislykkes:

SELECT * FROM tblServiceUsersSchedule 
WHERE TRY_CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
      < CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL

Bemærk: Jeg har brugt CAST(GETDATE() as Date) for at fjerne tidsdelen af ​​den aktuelle dato. Det betyder, at du kun får poster, hvor ScheduleEndDate er mindst en dag gammel. Hvis du også ønsker at få de poster, hvor ScheduleEndDate er i dag, brug <= i stedet for < .

En sidste ting: Brug af funktioner på kolonner i where-klausulen forhindrer SQL Server i at bruge indeksering på disse kolonner.
Dette er endnu en grund til, hvorfor du bør ændre dine kolonner til den passende datatype.



  1. SQL Server 2008 række Indsæt og opdater tidsstempler

  2. Charlotte SQL Server-brugergruppe:Rette langsomme forespørgsler. Hurtig.

  3. Registrer fortløbende datointervaller ved hjælp af SQL

  4. Sådan automatiseres processen med SQL Server Database Schema Synchronization