IT Staff

Blog về chuyên ngành IT

MSSQL bảo rằng 23:59:59:999 = 00:00:00:000

leave a comment »

Mọi báo cáo đều chạy đúng với bộ dữ liệu test, develop và product, chỉ cho đến cuối ngày hôm nay, em gái trong công ty la lên (lại nữa rồi!): “Báo cáo sai rồi, sai tét bét rồi“.

Sau khi xác định vấn đề đang xảy ra, giờ đây mọi thứ đều rối tung một cách khó hiểu, báo cáo – chúng hiển thị dữ liệu như một đứa trẻ (“cái gì cũng lấy, cái gì cũng đòi”), bất kể điều kiện chúng tôi đưa ra là chỉ lấy dữ liệu trong tháng 2 và chỉ trong tháng đó thôi. Nghĩa là,

min_boundary_datetime <= row.date_created <= max_boundary_datetime

trong đó:

min_boundary_datetime = 2012-02-01 00:00:00

max_boundary_datetime = 2012-02-29 23:59:59

Tôi debug mọi thứ vẫn ổn, nhưng dữ liệu load lên vẫn không đúng, nó không chỉ load lên tháng 2 mà cả luôn dữ liệu của ngày 01 tháng 03 của năm. Tôi cẩn thận kiểm thử rất nhiều trường hợp cả trong chương trình và chạy script test trong sql thì vẫn y xì vậy, tôi vẫn chưa hiểu, mọi điều kiện đưa ra đều đúng.

Tôi viết đoạn code nhỏ kiểm tra lại dữ liệu trả về với bộ filter ban đầu thì dữ liệu không thỏa => rõ ràng không thỏa điều kiện ban đầu, mà tại sao lại lấy lên được? Làm cho tới khi nào đã, đờ người ra thì tôi nhờ một anh trong nhóm cùng nhau kiểm tra cái này, dẫu sao thì hai vẫn tốt hơn một!

Chúng tôi vừa debug tỉ mỉ, vừa giải thích và khẳng định ý nghĩa của từng dòng code, và sau khi lặp lại nhiều lần thao tác mà tôi đã làm, thì kết quả vẫn không có gì là tiến triển.

Nghi ngờ đoạn biên trên có vấn đề, tôi bắt đầu lục lọi mấy đoạn init value cho các giá trị của điều kiện lọc. Tôi chạy lại báo cáo, và thay giá trị biên trên bằng biến temp_max_boundary_datetime có giá trị thiết lập bằng tay là “2012-02-29 23:59:59” và :action. Bravo, quá đẹp, giờ thì nó đã đã chạy đúng, tôi nhận ra là hôm nay nó trông rất đẹp (ý tôi là nó thực sự đẹp như một người phụ nữ vậy Smile :))

Tôi bắt đầu kiểm tra giá trị của max_boundary_datetime, sau khi xem đoạn code init value của nó thì tôi phát hiện có một điểm lạ: con số 999.

Ngưỡng mộ thật, trong quá trình sử dụng datetime, sự am hiểu của tôi về nó còn quá kém so với người viết đoạn code này:

DateTime max_boundary_datetime = newDateTime(year, month, DateTime .DaysInMonth(year, month), 23, 59, 59, 999);

Tôi phát hiện ra là ở trên, tôi có viết một đoạn code để gán giá trị tạm cho ngày để test (temp_max_boundary_datetime),  tôi quên chưa gán giá trị cho millisecond. Tôi gán lại, bắt đầu retest, và… kết quả lại chạy sai y như ban đầu, pótay! Vậy là chính xác số 999 này là nguyên nhân gây ra lỗi.  Tôi nghĩ mình nên tìm hiểu kỹ hơn về con số millisecond = 999 này.

Search trên msdn cho datetime (Transact-SQL), tôi tìm được cái này:

Xin lưu ý cho điều này khi bạn làm với cơ sở dữ liệu MS SQL rằng giá trị datetime được làm tròn tăng ở mức  .000, .003, hoặc .007 giây, đặc tả theo như dưới đây:

Giá trị người dùng gán   Giá trị hệ thống thực sự lưu trữ

01/01/98 23:59:59.999

  1998-01-02 00:00:00.000

01/01/98 23:59:59.995

01/01/98 23:59:59.996

01/01/98 23:59:59.997

01/01/98 23:59:59.998


  1998-01-01 23:59:59.997
01/01/98 23:59:59.99201/01/98 23:59:59.993

01/01/98 23:59:59.994


  1998-01-01 23:59:59.993
01/01/98 23:59:59.99001/01/98 23:59:59.991   1998-01-01 23:59:59.990

Và mọi chuyện đã rõ, chương trình của tôi mắc phải ở trường hợp đầu tiên, tôi thiết lập lại giá trị millisecond của biên trên thành 997 thì báo cáo chạy tốt. Thật vui vì mọi thứ đã trở lại bình thường.

Thực sự các báo cáo này chỉ quan trọng ở mức độ ngày, không quan tâm đến thời gian. Nên ban đầu, trong quá trình debug tôi không quan tâm đến giá trị millisecond cho lắm, do đó hơi siêng nên tôi gán luôn giá trị cho giờ, phút, giây cho biến test mà vẫn không ăn thua gì.

Bài học mà tôi rút ra (tuy cũ mà mới) là: một khi sử dụng cái gì thì phải: “đọc kỹ hướng dẫn sử dụng trước khi dùng”.

Build => Commit

Update build nào!

Written by Xavier

Tháng Tám 3, 2013 lúc 9:56 sáng

Posted in MSSQL

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s

%d bloggers like this: