Việc lưu trữ các giá trị ngày dưới dạng varchar chỉ là sai.
Nếu có thể, bạn nên thay đổi bảng để lưu trữ chúng dưới dạng kiểu dữ liệu ngày tháng.
Bạn có thể thực hiện điều đó trong một vài bước đơn giản:
-
Đổi tên các cột hiện tại (tôi đoán ScheduleStartDate cũng là varchar) thành columnName_old. Điều này có thể dễ dàng thực hiện bằng cách sử dụng
sp_rename
. -
Sử dụng
alter table
để thêm các cột với kiểu dữ liệu thích hợp. - Sao chép các giá trị từ các cột cũ sang các cột mới bằng cách sử dụng câu lệnh cập nhật. Vì tất cả các ngày được lưu trữ ở cùng một định dạng, bạn có thể sử dụng
convert
như thế này:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103)
Nếu phiên bản máy chủ sql của bạn là 2012 trở lên, hãy sử dụngtry_convert
. Lưu ý rằng tôi đã sử dụngnullif
,ltrim
vàrtrim
để chuyển đổi các giá trị chỉ chứa khoảng trắng thành rỗng. - Thả và tạo lại các chỉ mục tham chiếu đến các cột này. Cách đơn giản nhất để thực hiện việc này là nhấp chuột phải vào chỉ mục trên SSMS và chọn
script index as
->drop and create
. - Sử dụng
alter table
để xóa các cột cũ.
Lưu ý: nếu các cột này đang được tham chiếu trong bất kỳ đối tượng nào khác trên cơ sở dữ liệu, bạn cũng sẽ phải thay đổi các đối tượng này. Điều này bao gồm các thủ tục được lưu trữ, khóa ngoại, v.v. '.
Nếu bạn không thể thay đổi loại dữ liệu của các cột và phiên bản máy chủ sql của bạn thấp hơn năm 2012, bạn cần sử dụng chuyển đổi như sau:
SELECT * FROM tblServiceUsersSchedule
WHERE CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
< CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL
Lưu ý rằng nếu bạn có ngay cả một hàng trong đó dữ liệu của cột không ở định dạng dd / MM / yyyy, điều này sẽ gây ra lỗi.
Đối với phiên bản máy chủ sql 2012 trở lên, hãy sử dụng Try_convert
. Hàm này sẽ chỉ trả về null nếu chuyển đổi không thành công:
SELECT * FROM tblServiceUsersSchedule
WHERE TRY_CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
< CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL
Lưu ý: Tôi đã sử dụng CAST(GETDATE() as Date)
để xóa phần thời gian của ngày hiện tại. Điều này có nghĩa là bạn sẽ chỉ nhận được các bản ghi trong đó ScheduleEndDate
ít nhất một ngày tuổi. Nếu bạn cũng muốn lấy các bản ghi trong đó ScheduleEndDate
là ngày hôm nay, hãy sử dụng <=
thay vì <
.
Một điều cuối cùng: Việc sử dụng các hàm trên các cột trong mệnh đề where sẽ ngăn Máy chủ Sql sử dụng bất kỳ lập chỉ mục nào trên các cột này.
Đây là một lý do khác tại sao bạn nên thay đổi các cột của mình thành kiểu dữ liệu thích hợp.