Các giá trị DATETIME hoạt động như thế nào trong SQLite?


110

Tôi đang tạo ứng dụng Android và cần lưu ngày / giờ của bản ghi tạo. Tuy nhiên, tài liệu SQLite nói rằng "SQLite không có lớp lưu trữ dành riêng để lưu trữ ngày và / hoặc giờ" và nó "có khả năng lưu trữ ngày và giờ dưới dạng giá trị TEXT, REAL hoặc INTEGER".

Có lý do kỹ thuật nào để sử dụng loại này hơn loại khác không? Và một cột duy nhất có thể lưu trữ ngày tháng ở bất kỳ định dạng nào trong ba định dạng từ hàng này sang hàng khác không?

Tôi sẽ cần phải so sánh ngày sau. Ví dụ: trong các ứng dụng của mình, tôi sẽ hiển thị tất cả các bản ghi được tạo từ ngày A đến ngày B. Tôi lo lắng rằng việc không có cột DATETIME thực sự có thể làm cho việc so sánh khó khăn.


Câu trả lời:


83

SQlite không có loại ngày giờ cụ thể. Bạn có thể sử dụng TEXT, REALhoặc INTEGERcác loại, nào phù hợp với nhu cầu của bạn.

Trực tiếp từ DOCS

SQLite không có một lớp lưu trữ dành riêng cho việc lưu trữ ngày và / hoặc giờ. Thay vào đó, các Hàm Ngày và Giờ tích hợp của SQLite có khả năng lưu trữ ngày và giờ dưới dạng các giá trị TEXT, REAL hoặc INTEGER:

  • TEXT dưới dạng chuỗi ISO8601 ("YYYY-MM-DD HH: MM: SS.SSS").
  • THỰC như số ngày Julian, số ngày kể từ buổi trưa ở Greenwich vào ngày 24 tháng 11 năm 4714 trước Công nguyên theo lịch Gregory sơ khai.
  • INTEGER dưới dạng Unix Time, số giây kể từ 1970-01-01 00:00:00 UTC.

Các ứng dụng có thể chọn lưu trữ ngày và giờ ở bất kỳ định dạng nào trong số này và tự do chuyển đổi giữa các định dạng bằng cách sử dụng các chức năng ngày và giờ được tích hợp sẵn.

Có thể tìm thấy các hàm Ngày và Giờ tích hợp trong SQLite tại đây .


11
Điều quan trọng cần lưu ý - tất cả các phương pháp lưu trữ ngày tháng đều sử dụng các định dạng có thể được so sánh bằng cách sử dụng các toán tử tiêu chuẩn =, <,> và GIỮA.
Larry Lustig

2
"SQLite không có một bộ lớp lưu trữ ngoài để lưu trữ ngày và / hoặc thời gian" - ngoại trừ nó có kiểu DATE và DATETIME mà không bao giờ được đề cập trong tài liệu hướng dẫn
Slabko

12
@Slabko Nó không. SQLite cho phép bất kỳ thứ gì (kể cả DATETIME) làm kiểu cột được khai báo. Dựa trên đó, nó cung cấp cho cột đó một mối quan hệ với một lớp lưu trữ (thậm chí nó còn có ví dụ về cách hoạt động của nó đối với DATETIME trong tài liệu). Mối quan hệ đó giống như một gợi ý, vì mỗi mục nhập cột thực sự có thể có một lớp lưu trữ khác nhau. Một lớp lưu trữ vẫn yếu hơn một bước so với một loại và có thể được hỗ trợ bởi nhiều loại. Vì vậy, có, bạn có thể sử dụng DATETIME. Không, nó không thực sự hỗ trợ nó như một kiểu hoặc lớp lưu trữ. Có, tài liệu thực sự chứa từ "DATETIME".
Jasper

20

SQLite không có một lớp lưu trữ dành riêng cho việc lưu trữ ngày và / hoặc giờ. Thay vào đó, các Hàm Ngày và Giờ tích hợp của SQLite có khả năng lưu trữ ngày và giờ dưới dạng các giá trị TEXT, REAL hoặc INTEGER:

TEXT dưới dạng chuỗi ISO8601 ("YYYY-MM-DD HH: MM: SS.SSS"). THỰC như số ngày Julian, số ngày kể từ buổi trưa ở Greenwich vào ngày 24 tháng 11 năm 4714 trước Công nguyên theo lịch Gregory sơ khai. INTEGER dưới dạng Unix Time, số giây kể từ 1970-01-01 00:00:00 UTC. Các ứng dụng có thể chọn lưu trữ ngày và giờ ở bất kỳ định dạng nào trong số này và tự do chuyển đổi giữa các định dạng bằng cách sử dụng các chức năng ngày và giờ được tích hợp sẵn.

Phải nói rằng, tôi sẽ sử dụng INTEGER và lưu trữ giây kể từ kỷ nguyên Unix (1970-01-01 00:00:00 UTC).


1
Tôi cũng thích điều này hơn. Dù sao thì các lớp liên quan đến ngày / giờ tiêu chuẩn cũng được hỗ trợ nội bộ bởi longs và khá dễ dàng để so sánh các long.
Karakuri

1
@dtmilano Tại sao bạn thích INTEGER ở đây thay vì Chuỗi?
IgorGanapolsky

1
INTEGER chỉ sử dụng 8 byte, TEXT đang sử dụng 23 byte trong ví dụ này. Tôi không rõ làm thế nào để chọn kiểu nó lưu trữ dữ liệu. Có nghĩa là nếu tôi tạo một cột kiểu INTEGER, các hàm sẽ tự động lưu trữ dưới dạng Unix Time?
rayzinnz

2
REAL cũng sử dụng 8 byte. Epoch giây sẽ có 10 chữ số cho đến cuối năm 2286 và vì IEEE double hỗ trợ 15-17 chữ số có nghĩa , điều này mang lại cho bạn độ phân giải tốt hơn so với mili giây. RSQLitedường như đang chuyển đổi POSIXctsang kỷ nguyên số, vì vậy nó hoạt động đủ tốt đối với tôi.
r2evans

@ r2evans Tôi không chắc bạn đang nói gì. Nếu tôi muốn lưu trữ mili giây kể từ Kỷ nguyên, làm cách nào để thực hiện điều đó?
Michael

14

Một trong những tính năng mạnh mẽ của SQLite là cho phép bạn chọn kiểu lưu trữ. Ưu điểm / nhược điểm của từng loại trong ba loại có thể khác nhau:

  • Chuỗi ISO8601

    • So sánh chuỗi cho kết quả hợp lệ
    • Lưu trữ phân số giây, tối đa ba chữ số thập phân
    • Cần thêm dung lượng lưu trữ
    • Bạn sẽ thấy trực tiếp giá trị của nó khi sử dụng trình duyệt cơ sở dữ liệu
    • Cần phân tích cú pháp cho các mục đích sử dụng khác
    • công cụ sửa đổi cột "default current_timestamp" sẽ lưu trữ bằng định dạng này
  • Số thực

    • Độ chính xác cao về phần giây
    • Khoảng thời gian dài nhất
  • Số nguyên

    • Không gian lưu trữ thấp nhất
    • Hoạt động nhanh chóng
    • Phạm vi thời gian nhỏ
    • Vấn đề năm 2038 có thể xảy ra

Nếu bạn cần so sánh các kiểu khác nhau hoặc xuất sang ứng dụng bên ngoài, bạn có thể tự do sử dụng các chức năng chuyển đổi ngày giờ của SQLite nếu cần.


1
Tại sao có vấn đề năm 2038? INTEGER dường như hỗ trợ lưu trữ 64 bit.
guan boshen

1
@guanboshen Theo như tôi có thể nói, lý do duy nhất để lo lắng về năm 2038 sẽ là hỗ trợ trên nền tảng máy chủ. Tài liệu SQLite tuyên bố sử dụng C's localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) trong triển khai tham chiếu và localtime()có thể dễ bị tấn công vào năm 2038 nếu nền tảng máy chủ có 32-bit time_t. Điều đó nói rằng, vì SQLite tuyên bố sẽ đề phòng khả năng này bằng cách ánh xạ các ngày bên ngoài thành một chuyển đổi trước trong phạm vi an toàn (xem cùng một liên kết), tôi nghĩ rằng nó không có khả năng là một vấn đề ngoại trừ có thể trong các trường hợp bí truyền.
Zoë Sparks

@ ZoëSparks Cảm ơn bạn đã làm rõ.
guan boshen

7

Đối với thực tế tất cả các vấn đề về ngày và giờ, tôi thích đơn giản hóa mọi thứ, rất, rất đơn giản ... Xuống từng giây được lưu trữ trong số nguyên.

Số nguyên sẽ luôn được hỗ trợ dưới dạng số nguyên trong cơ sở dữ liệu, tệp phẳng, v.v. Bạn thực hiện một phép toán nhỏ và chuyển nó thành một kiểu khác và bạn có thể định dạng ngày tháng theo ý muốn.

Làm theo cách này, bạn không phải lo lắng khi [chèn cơ sở dữ liệu yêu thích hiện tại vào đây] bị thay thế bằng [cơ sở dữ liệu yêu thích trong tương lai] mà tình cờ không sử dụng định dạng ngày bạn chọn hôm nay.

Nó chỉ là một chút chi phí toán học (ví dụ: phương pháp - mất hai giây, tôi sẽ đăng ý chính nếu cần) và đơn giản hóa mọi thứ cho rất nhiều thao tác liên quan đến ngày / giờ sau này.


7

Lưu trữ nó trong một trường loại long. Xem Date.getTime()new Date(long)


làm thế nào tôi có thể so sánh nó ?? u có thể cho tôi mẫu của truy vấn ..: D
Khairil Ushan

Xem Joda Time để so sánh trong mã ( joda-time.sourceforge.net ) và sử dụng so sánh dài đơn giản trong SQL (ví dụ: so sánh số).
Cú pháp

chọn * từ bảng nơi tạo giữa a và b;
koem
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.