sql >> Databasteknik >  >> RDS >> Sqlserver

Jämföra datum lagrade som varchar

Att lagra datumvärden som varchar är helt enkelt fel.

Om möjligt bör du ändra tabellen för att lagra dem som datumdatatyp.
Du kan göra det med några enkla steg:

  1. Byt namn på de nuvarande kolumnerna (jag antar att ScheduleStartDate också är varchar) till columnName_old. Detta kan enkelt göras genom att använda sp_rename .

  2. Använd alter table för att lägga till kolumnerna med lämplig datatyp.

  3. Kopiera värdena från de gamla kolumnerna till de nya kolumnerna med hjälp av en uppdateringssats. Eftersom alla datum lagras i samma format kan du använda convert så här:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103) Om din sql-serverversion är 2012 eller senare, använd try_convert . Observera att jag har använt nullif , ltrim och rtrim för att konvertera värden som bara innehåller blanksteg till null.
  4. Släpp och återskapa index som refererar till dessa kolumner. Det enklaste sättet att göra detta är genom att högerklicka på indexet på SSMS och välja script index as -> drop and create .
  5. Använd alter table för att ta bort de gamla kolumnerna.

Obs! om dessa kolumner refereras i andra objekt i databasen måste du ändra dessa objekt också. Detta inkluderar lagrade procedurer, främmande nycklar etc.

Om du inte kan ändra datatyperna av kolumnerna, och din sql-serverversion är lägre än 2012, måste du använda konvertera så här:

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

Observera att om du ens har en enda rad där kolumnens data inte är i formatet dd/MM/åååå kommer detta att ge upphov till ett fel.

För sql-serverversioner 2012 eller senare, använd Try_convert . Denna funktion kommer helt enkelt att returnera null om konverteringen misslyckas:

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

Obs! Jag har använt CAST(GETDATE() as Date) för att ta bort tidsdelen av det aktuella datumet. Det betyder att du bara kommer att få poster där ScheduleEndDate är minst en dag gammal. Om du också vill få posterna där ScheduleEndDate är idag, använd <= istället för < .

En sista sak: Att använda funktioner på kolumner i where-satsen kommer att förhindra SQL Server att använda någon indexering på dessa kolumner.
Detta är ännu en anledning till varför du bör ändra dina kolumner till lämplig datatyp.



  1. MySql:MyISAM vs. Inno DB!

  2. Vad är logisk OCH operatör i SQL Server - SQL Server / TSQL Tutorial Del 120

  3. oracle drop index om det finns

  4. Hur kan jag se frågor som körs mot Oracle?