Đang tải...

Oracle DATE vs VARCHAR lưu MM/yyyy - những cái bẫy tôi từng gặp

13/05/2026
8 phút đọc
Oracle DATE vs VARCHAR lưu MM/yyyy - những cái bẫy tôi từng gặp
# Mở đầu Trong một dự án cũ, không biết từ bao giờ, do ai làm, tại sao lại làm như vậy. Ngay cả leader của tôi - người có thâm niên gần 10 năm ở công ty - c...

Mở đầu

Trong một dự án cũ, không biết từ bao giờ, do ai làm, tại sao lại làm như vậy. Ngay cả leader của tôi - người có thâm niên gần 10 năm ở công ty - cũng chỉ biết đó là một huyền thoại chỉ còn lưu lại trong sử sách của công ty. Ngay cả git history cũng không còn lại tên của anh. Người ấy đã để lại một di sản đó là lưu Kỳ dữ liệu theo format MM/yyyy ví dụ như 11/2025, 2/2026,... và anh đã lưu nó thành VARCHAR. Và tôi chính là thằng được thừa kế lại cái di sản này của anh chỉ sau hơn 1 tháng thử việc.

Ban đầu đọc qua thì mọi việc đang rất là trơn tru và hợp lý:

  • dễ đọc
  • đúng nghiệp vụ
  • FE hiển thị tiện

Cho tới khi, công ty chúng tôi bắt đầu phất lên, lượng người dùng ngày càng lớn, theo đó lượng data mà database phải gánh là một con số rất là wow. Khi đó chúng tôi dần dần nhận ra các vấn đề:

  • query filter bắt đầu sai
  • sort dữ liệu bị lệch
  • Oracle TO_DATE() nổ lỗi
  • index gần như vô dụng
  • và performance tụt không phanh

Với sự hỗ trợ nhiệt tình của sếp tôi đã nhận ra được đâu là những cái bẫy mà thằng sinh viên chân ướt chân ráo bước chân vào thị trường lao động gặp phải khi làm việc với Oracle DATE và VARCHAR cho dữ liệu dạng MM/yyyy.

1. Sort bằng VARCHAR không phải lúc nào cũng đúng

Nếu format save vào db không chuẩn:

1/2026
10/2025
2/2026

Sau khi sort theo String ta sẽ có:

1/2026
10/2025
2/2026

=> Nó làm cho trình tự thời gian hoàn toàn sai lệch. Chẳng hiểu sao trong suốt thời gian trước đó QC công ty không thấy chỗ này lỗi 😬

Ngoài ra tôi còn tìm thấy rất nhiều data rác kiểu

  • không padding 01
  • dữ liệu cũ nhập tay
  • ETL import lỗi

=> Lúc đầu mới nhận tìm hiểu tôi ngợp luôn mà. Mỗi chỗ một kiểu thế này thì làm như nào trời. Xong cái chỗ này anh leader phải xắn tay áo vào viết sql giúp tôi chuẩn hóa dữ liệu về MM/yyyy mà :(. Nghĩ lại thấy ngày xưa mình báo anh nhiều quá.

2. TO_DATE() với MM/YYYY rất dễ hiểu sai

Ví dụ:

TO_DATE('02/2026', 'MM/YYYY')

Oracle sẽ convert thành:

01/02/2026 00:00:00

Nghĩa là: ngày mặc định = 1

Nhiều người (hoặc là chỉ có mình tôi) tưởng: tháng 02 năm 2026

Nhưng thực tế nó vẫn là một DATE đầy đủ.

3. So sánh DATE và VARCHAR cực nguy hiểm

Ví dụ bảng lưu:

KY_DU_LIEU = '02/2026'

Query:

WHERE TO_DATE(KY_DU_LIEU, 'MM/YYYY')
 >= TO_DATE('09/01/2025', 'DD/MM/YYYY')

Thoạt nhìn có vẻ đúng. Nhưng:

vế trái = 01/02/2026
vế phải = 09/01/2025

Nghĩa là đang compare:

01/02/2026 >= 09/01/2025

Không còn là compare theo tháng nữa. Về logic để đi cãi nhau với QC thì mình có sai đâu. Mình đúng mà. Mình chỉ sai với chính mình thôi 🤫

À đừng bạn nào bảo mình sao không truy vấn kiểu:

WHERE KY_DU_LIEU = '09/01/2025'

nhé. Tại nghiệp vụ bên mình cần lấy dữ liệu trong nhiều kỳ nữa á 🥲. Từ kỳ X đến kỳ Y mà xài OR hay IN thì hơi bị kỳ :(

4. Dùng function lên column khiến index gần như mất tác dụng

Ví dụ:

WHERE TO_DATE(KY_DU_LIEU, 'MM/YYYY') >= :fromDate

Khi này Oracle sẽ phải:

  • convert từng row
  • scan dữ liệu
  • khó dùng index

=> bảng vài triệu records sẽ rất rất tốn hiệu năng. Cơ bản là toangg

5. BETWEEN với VARCHAR là cái bẫy khủng khiếp

Ví dụ:

WHERE KY_DU_LIEU BETWEEN '01/2025' AND '12/2025'

Nhìn qua thì nghĩ là đúng đấy. Nhưng thực chất việc ta đang làm là compare string. Nếu dữ liệu không normalize:

1/2025
2/2025
10/2025

=> kết quả có thể sai hoàn toàn.

Giải pháp

Sau khi họp hành 7749 buổi. Chỉ ra vô số điểm bất lợi các thứ các kiểu cho ban lãnh đạo xem (này sếp tôi là nha, chứ tôi mà đứng thuyết trình khéo mai nhận trát nghỉ việc luôn quá) thì CR để thay đổi trường dữ liệu này cũng đã được thông qua. Cụ thể chúng tôi đã chuyển sang lưu bằng LocalDate

01/MM/YYYY

Ví dụ:

01/02/2026

chứ không còn là String nữa hẹ hẹ. Khi đó khi sử dụng sẽ nhàn và chính xác đến vô cùng

  • query bằng DATE thật
  • index hoạt động
  • sort đúng
  • range query đúng

À nhờ cái này tôi còn được sếp chỉ có cái mapstruct để convert ra dạng MM/yyyy để trả cho FE nữa. Đỡ phải map thủ công. Oách xà lách vô cùng đối với thằng sinh viên thử việc như tôi.

Tổng kết

Qua sự chỉ bảo tận tình của sếp(thề là anh ấy không mắng chửi câu nào) tôi đã học được dữ liệu thời gian gần như luôn nên lưu bằng kiểu DATE/TIMESTAMP thật. VARCHAR chỉ trông đơn giản lúc ban đầu. Nhưng khi hệ thống lớn dần, nguy cơ cũng dần dần được tạo ra:

  • filter
  • sort
  • range query
  • index
  • performance
  • và validate dữ liệu

sẽ trở thành một mớ rất khó kiểm soát(cũng may là vẫn còn cứu được hẹ hẹ).

Các bro nào mà vào công ty XXX. Thấy đoạn code thời còn sinh viên của tôi. Thì dành 1 phút tưởng niệm cho tôi và anh leader H giấu tên nha. À mà tôi nhảy công ty khác rồi. Thấy code tôi sai thì fix đi không chửi được đâu :v:

Bài viết dựa trên kinh nghiệm, trải nghiệm của bản thân. Có điểm nào chưa đúng, sai lệch mong mọi người góp ý phía dưới phần comment. Tôi sẽ ghi nhận và sửa đổi. Cảm ơn tất cả mọi người đã dành thời gian đọc bài.

📚 Nguồn: Viblo

Chia sẻ bài viết

Cần tư vấn?

Liên hệ với chúng tôi để được hỗ trợ

Liên hệ ngay

Bài viết liên quan

🤖 Building Social Games with AI — The Practitioner's Guide 📖
14/05/2026

🤖 Building Social Games with AI — The Practitioner's Guide 📖

> A comprehensive, opinionated, actionable guide for **using AI to build, ship, and operate social games** in the lineage covered by [🌾 The Social Games Playbook 🎮](https://dev.to/truongpx396/th...

Đọc thêm
qs88nl5001
14/05/2026

qs88nl5001

qs88 mang đến sân chơi giải trí trực tuyến chuyên nghiệp với hệ thống vận hành ổn định cùng tốc độ xử lý nhanh chóng. Người tham gia dễ dàng tiếp cận h...

Đọc thêm
Claude đã giúp lưu lượng truy cập website của tôi tăng gấp đôi như thế nào ?
14/05/2026

Claude đã giúp lưu lượng truy cập website của tôi tăng gấp đôi như thế nào ?

> Bài viết này được tổng hợp và diễn giải lại từ bài gốc ["Claude is Doubling My Website Traffic"](https://nick-nolan.medium.com/claude-is-doubling-my-website-traffic-1a26a793b...

Đọc thêm

Bắt đầu dự án của bạn

Hãy để Flash Dev đồng hành cùng bạn

Liên hệ ngay