Lưu trữ dữ liệu trong một cột là cách ưa thích, vì chúng được liên kết chặt chẽ. Một điểm trong thời gian là một mẩu thông tin, không phải hai.
Một cách phổ biến để lưu trữ dữ liệu ngày / giờ, được sử dụng "đằng sau hậu trường" của nhiều sản phẩm, bằng cách chuyển đổi nó thành giá trị thập phân trong đó "ngày" là phần nguyên của giá trị thập phân và "thời gian" là phân số giá trị. Vì vậy, 1900-01-01 00:00:00 được lưu trữ là 0.0 và ngày 20 tháng 9 năm 2016 9:34:00 được lưu trữ dưới dạng 42631,39861. 42631 là số ngày kể từ 1900-01-01. .39861 là phần thời gian trôi qua kể từ nửa đêm. Không sử dụng loại thập phân trực tiếp để làm điều này, sử dụng loại ngày / giờ rõ ràng; quan điểm của tôi ở đây chỉ là một minh họa.
Lưu trữ dữ liệu trong hai cột riêng biệt có nghĩa là bạn sẽ cần kết hợp cả hai giá trị cột bất cứ lúc nào bạn muốn xem liệu một thời điểm nhất định sớm hơn hoặc muộn hơn giá trị được lưu trữ.
Nếu bạn lưu trữ các giá trị một cách riêng biệt, bạn sẽ luôn gặp phải các "lỗi" rất khó phát hiện. Lấy ví dụ như sau:
IF OBJECT_ID('tempdb..#DT') IS NOT NULL
DROP TABLE #DT;
CREATE TABLE #DT
(
dt_value DATETIME NOT NULL
, d_value DATE NOT NULL
, t_value TIME(0) NOT NULL
);
DECLARE @d DATETIME = '2016-09-20 09:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
SET @d = '2016-09-20 11:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.dt_value >= '2016-07-01 11:00:00';
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.d_value >= CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00');
Trong đoạn mã trên, chúng tôi đang tạo một bảng thử nghiệm, điền vào đó hai giá trị, sau đó thực hiện một truy vấn đơn giản đối với dữ liệu đó. Hàng đầu tiên SELECT
trả về cả hai hàng, tuy nhiên hàng thứ hai SELECT
chỉ trả về một hàng duy nhất, có thể không phải là kết quả mong muốn:
Cách chính xác để lọc phạm vi ngày / thời gian trong đó các giá trị nằm trong các cột riêng biệt, như được chỉ ra bởi @ypercube trong các nhận xét, là:
WHERE dt.d_value > CONVERT(DATE, '2016-07-01') /* note there is no time component here */
OR (
dt.d_value = CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00')
)
Nếu bạn cần tách thành phần thời gian cho mục đích phân tích , bạn có thể xem xét thêm cột được tính toán, duy trì, cho phần thời gian của giá trị:
ALTER TABLE #DT
ADD dt_value_time AS CONVERT(TIME(0), dt_value) PERSISTED;
SELECT *
FROM #dt;
Cột tồn tại sau đó có thể được lập chỉ mục cho phép sắp xếp nhanh, v.v., theo thời gian trong ngày.
Nếu bạn đang xem xét phân chia ngày và thời gian thành hai trường cho mục đích hiển thị, bạn nên nhận ra rằng định dạng nên được thực hiện tại máy khách, không phải máy chủ.