Съхраняването на стойности за дата като varchar е просто погрешно.
Ако е възможно, трябва да промените таблицата, за да ги съхранявате като тип данни за дата.
Можете да го направите с няколко прости стъпки:
-
Преименувайте текущите колони (предполагам, че ScheduleStartDate също е varchar) на columnName_old. Това може лесно да се направи с помощта на
sp_rename
. -
Използвайте
alter table
за да добавите колоните с подходящия тип данни. - Копирайте стойностите от старите колони в новите колони, като използвате израз за актуализиране. Тъй като всички дати се съхраняват в един и същ формат, можете да използвате
convert
така:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103)
Ако версията на вашия sql сървър е 2012 или по-нова, използвайтеtry_convert
. Имайте предвид, че използвахnullif
,ltrim
иrtrim
за да преобразувате стойности, които съдържат само бели интервали, в нула. - Пустнете и създайте отново индекси, които препращат към тези колони. Най-простият начин да направите това е като щракнете с десния бутон върху индекса на SSMS и изберете
script index as
->drop and create
. - Използвайте
alter table
за да премахнете старите колони.
Забележка: ако тези колони се препращат в други обекти в базата данни, ще трябва да промените и тези обекти. Това включва съхранени процедури, външни ключове и т.н.
Ако не можете да промените типовете данни от колоните и версията на вашия sql сървър е по-ниска от 2012 г., трябва да използвате convert по следния начин:
SELECT * FROM tblServiceUsersSchedule
WHERE CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
< CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL
Имайте предвид, че ако имате дори един ред, където данните на колоната не са във формат dd/MM/yyyy, това ще доведе до грешка.
За версии на sql сървър 2012 или по-нови, използвайте Try_convert
. Тази функция просто ще върне null, ако преобразуването не успее:
SELECT * FROM tblServiceUsersSchedule
WHERE TRY_CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
< CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL
Забележка: Използвах CAST(GETDATE() as Date)
за да премахнете частта от времето на текущата дата. Това означава, че ще получавате само записи, където ScheduleEndDate
е на поне един ден. Ако искате да получите и записите, където ScheduleEndDate
е днес, използвайте <=
вместо <
.
Едно последно: Използването на функции върху колони в клаузата where ще попречи на Sql Server да използва каквото и да е индексиране на тези колони.
Това е още една причина, поради която трябва да промените колоните си на подходящия тип данни.