ค่า DATETIME ทำงานอย่างไรใน SQLite


111

ฉันกำลังสร้างแอพ Android และต้องการบันทึกวันที่ / เวลาของบันทึกการสร้าง อย่างไรก็ตามเอกสาร SQLite กล่าวว่า "SQLite ไม่มีคลาสพื้นที่เก็บข้อมูลที่ตั้งไว้สำหรับจัดเก็บวันที่และ / หรือเวลา" และ "สามารถจัดเก็บวันที่และเวลาเป็นค่า TEXT, REAL หรือ INTEGER ได้"

มีเหตุผลทางเทคนิคที่จะใช้ประเภทหนึ่งกับอีกประเภทหนึ่งหรือไม่? และคอลัมน์เดียวสามารถจัดเก็บวันที่ในรูปแบบสามรูปแบบจากแถวหนึ่งไปอีกแถวได้หรือไม่?

ฉันจะต้องเปรียบเทียบวันที่ในภายหลัง ตัวอย่างเช่นในแอปของฉันฉันจะแสดงบันทึกทั้งหมดที่สร้างขึ้นระหว่างวันที่ A จนถึงวันที่ B ฉันกังวลว่าการไม่มีคอลัมน์ DATETIME ที่แท้จริงอาจทำให้การเปรียบเทียบทำได้ยาก


คำตอบ:


84

SQlite ไม่มีประเภทวันที่และเวลาที่เฉพาะเจาะจง คุณสามารถใช้TEXT, REALหรือINTEGERประเภทแล้วแต่จำนวนใดเหมาะสมกับความต้องการของคุณ

ตรงจาก DOCS

SQLite ไม่มีคลาสพื้นที่จัดเก็บไว้สำหรับจัดเก็บวันที่และ / หรือเวลา ฟังก์ชันวันที่และเวลาในตัวของ SQLite สามารถจัดเก็บวันที่และเวลาเป็นค่า TEXT, REAL หรือ INTEGER แทนได้:

  • TEXT เป็นสตริง ISO8601 ("YYYY-MM-DD HH: MM: SS.SSS")
  • จริงเป็นตัวเลขวันของจูเลียนจำนวนวันนับตั้งแต่เที่ยงในกรีนิชเมื่อวันที่ 24 พฤศจิกายน 4714 ปีก่อนคริสตกาลตามปฏิทินเกรกอเรียนโปรเลปติก
  • INTEGER เป็นเวลา Unix จำนวนวินาทีตั้งแต่ 1970-01-01 00:00:00 UTC

แอปพลิเคชันสามารถเลือกจัดเก็บวันที่และเวลาในรูปแบบเหล่านี้และแปลงระหว่างรูปแบบได้อย่างอิสระโดยใช้ฟังก์ชันวันที่และเวลาในตัว

SQLite ในตัววันที่และฟังก์ชั่นเวลาที่สามารถพบได้ที่นี่


11
สิ่งสำคัญที่ควรทราบ - วิธีการจัดเก็บวันที่ทั้งหมดใช้รูปแบบที่สามารถเปรียบเทียบได้โดยใช้ตัวดำเนินการมาตรฐาน =, <,> และ BETWEEN
Larry Lustig

2
"SQLite ไม่มีคลาสพื้นที่จัดเก็บสำรองไว้สำหรับจัดเก็บวันที่และ / หรือเวลา" ยกเว้นว่าจะมีประเภท DATE และ DATETIME ซึ่งไม่เคยกล่าวถึงในเอกสารประกอบ
Slabko

12
@Slabko มันไม่ได้ SQLite อนุญาตให้ทุกอย่าง (รวมถึง DATETIME) เป็นประเภทคอลัมน์ที่ประกาศ จากนั้นทำให้คอลัมน์นั้นมีความสัมพันธ์กับคลาสพื้นที่เก็บข้อมูล (มีตัวอย่างวิธีการทำงานสำหรับ DATETIME ในเอกสารประกอบ) ความสัมพันธ์นั้นเป็นเหมือนคำใบ้มากกว่าเนื่องจากแต่ละรายการในคอลัมน์อาจมีคลาสพื้นที่เก็บข้อมูลที่แตกต่างกัน คลาสพื้นที่เก็บข้อมูลยังคงเป็นขั้นตอนที่อ่อนแอกว่าประเภทและสามารถสำรองได้หลายประเภท ใช่คุณสามารถใช้ DATETIME ไม่มันไม่รองรับเป็นประเภทหรือคลาสพื้นที่เก็บข้อมูล ใช่เอกสารนี้มีคำว่า "DATETIME" อยู่
Jasper

20

SQLite ไม่มีคลาสพื้นที่จัดเก็บไว้สำหรับจัดเก็บวันที่และ / หรือเวลา ฟังก์ชันวันที่และเวลาในตัวของ SQLite สามารถจัดเก็บวันที่และเวลาเป็นค่า TEXT, REAL หรือ INTEGER แทนได้:

TEXT เป็นสตริง ISO8601 ("YYYY-MM-DD HH: MM: SS.SSS") จริงเป็นตัวเลขวันของจูเลียนจำนวนวันนับตั้งแต่เที่ยงในกรีนิชเมื่อวันที่ 24 พฤศจิกายน 4714 ปีก่อนคริสตกาลตามปฏิทินเกรกอเรียนโปรเลปติก INTEGER เป็นเวลา Unix จำนวนวินาทีตั้งแต่ 1970-01-01 00:00:00 UTC แอปพลิเคชันสามารถเลือกจัดเก็บวันที่และเวลาในรูปแบบเหล่านี้และแปลงระหว่างรูปแบบได้อย่างอิสระโดยใช้ฟังก์ชันวันที่และเวลาในตัว

ต้องบอกว่าฉันจะใช้INTEGERและเก็บวินาทีตั้งแต่ยุค Unix (1970-01-01 00:00:00 UTC)


1
ฉันชอบสิ่งนี้เช่นกัน คลาสที่เกี่ยวข้องกับวันที่ / เวลามาตรฐานได้รับการสนับสนุนภายในโดย longs อยู่แล้วและมันค่อนข้างง่ายที่จะเปรียบเทียบ longs
Karakuri

1
@dtmilano ทำไมคุณถึงชอบ INTEGER ที่นี่แทนที่จะเป็น String?
IgorGanapolsky

1
INTEGER ใช้ 8 ไบต์เท่านั้น TEXT ใช้ 23 ไบต์ในตัวอย่างนี้ ยังไม่ชัดเจนว่าจะเลือกประเภทที่เก็บข้อมูลไว้อย่างไรหมายความว่าถ้าฉันสร้างคอลัมน์ประเภท INTEGER ฟังก์ชันต่างๆจะจัดเก็บเป็น Unix Time โดยอัตโนมัติหรือไม่
rayzinnz

2
REAL ใช้ 8 ไบต์เช่นกัน ยุควินาทีจะเป็น 10 หลักจนถึงปลายปี 2286 และเนื่องจาก IEEE double รองรับเลขนัยสำคัญ 15-17 ตัวจึงให้ความละเอียดที่ดีกว่ามิลลิวินาที RSQLiteดูเหมือนว่าจะแปลงPOSIXctเป็นยุคตัวเลขดังนั้นจึงใช้ได้ดีสำหรับฉัน
r2evans

@ r2evans ฉันไม่แน่ใจว่าคุณพูดอะไร ถ้าฉันต้องการจัดเก็บมิลลิวินาทีตั้งแต่ Epoch ฉันจะทำอย่างไร?
Michael

14

คุณสมบัติที่มีประสิทธิภาพอย่างหนึ่งของ SQLite คือช่วยให้คุณสามารถเลือกประเภทการจัดเก็บ ข้อดี / ข้อเสียของความเป็นไปได้ที่แตกต่างกันสามประการ:

  • สตริง ISO8601

    • การเปรียบเทียบสตริงให้ผลลัพธ์ที่ถูกต้อง
    • เก็บเศษเสี้ยววินาทีได้ถึงทศนิยมสามหลัก
    • ต้องการพื้นที่จัดเก็บเพิ่มเติม
    • คุณจะเห็นคุณค่าของมันโดยตรงเมื่อใช้เบราว์เซอร์ฐานข้อมูล
    • ต้องการการแยกวิเคราะห์สำหรับการใช้งานอื่น ๆ
    • ตัวปรับแต่งคอลัมน์ "default current_timestamp" จะจัดเก็บโดยใช้รูปแบบนี้
  • เบอร์จริง

    • ความแม่นยำสูงเกี่ยวกับเศษเสี้ยววินาที
    • ช่วงเวลาที่ยาวที่สุด
  • เลขจำนวนเต็ม

    • พื้นที่จัดเก็บต่ำที่สุด
    • การดำเนินงานด่วน
    • ช่วงเวลาเล็ก ๆ
    • ปัญหาปี 2581 ที่เป็นไปได้

หากคุณต้องการเปรียบเทียบประเภทต่างๆหรือส่งออกไปยังแอปพลิเคชันภายนอกคุณสามารถใช้ฟังก์ชันการแปลงวันที่และเวลาของ SQLite ได้ตามต้องการ


1
ทำไมถึงมีปัญหา 2038? INTEGER ดูเหมือนว่าจะรองรับพื้นที่เก็บข้อมูล 64 บิต
guan boshen

1
@guanboshen เท่าที่ฉันบอกได้เหตุผลเดียวที่ต้องกังวลเกี่ยวกับปี 2038 คือการรองรับบนแพลตฟอร์มโฮสต์ การเรียกร้องเอกสาร SQLite ใช้ของ C localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) ในการดำเนินการอ้างอิงและlocaltime()อาจจะเสี่ยงต่อการ 2038 ถ้าแพลตฟอร์มเจ้าภาพมี time_t32 ที่กล่าวว่าเนื่องจาก SQLite อ้างว่าป้องกันความเป็นไปได้นี้โดยการแมปวันที่ภายนอกลงในช่วงก่อนการแปลงที่ปลอดภัย (ดูลิงก์เดียวกัน) ฉันคิดว่าไม่น่าจะเป็นปัญหายกเว้นในกรณีที่เป็นความลับ
Zoë Sparks

@ ZoëSparksขอบคุณสำหรับคำชี้แจง
guan boshen

7

สำหรับเรื่องวันที่และเวลาในทางปฏิบัติฉันชอบทำให้สิ่งต่างๆง่ายขึ้นง่ายมาก ... เหลือไม่กี่วินาทีที่เก็บไว้ในจำนวนเต็ม

จำนวนเต็มจะได้รับการสนับสนุนเป็นจำนวนเต็มในฐานข้อมูลไฟล์แบบแบนและอื่น ๆ เสมอคุณทำคณิตศาสตร์เล็กน้อยแล้วโยนเป็นประเภทอื่นและคุณสามารถจัดรูปแบบวันที่ได้ตามที่คุณต้องการ

ด้วยวิธีนี้คุณไม่ต้องกังวลเมื่อ [ใส่ฐานข้อมูลรายการโปรดปัจจุบันที่นี่] ถูกแทนที่ด้วย [ฐานข้อมูลรายการโปรดในอนาคต] ซึ่งบังเอิญไม่ได้ใช้รูปแบบวันที่ที่คุณเลือกในวันนี้

มันเป็นเพียงค่าใช้จ่ายทางคณิตศาสตร์เล็กน้อย (เช่นวิธีการ - ใช้เวลาสองวินาทีฉันจะโพสต์ส่วนสำคัญหากจำเป็น) และทำให้สิ่งต่างๆง่ายขึ้นสำหรับการดำเนินการจำนวนมากเกี่ยวกับวันที่ / เวลาในภายหลัง


7

longเก็บไว้ในด้านการพิมพ์ ดูDate.getTime()และnew Date(long)


เปรียบเทียบได้ยังไง ?? คุณสามารถให้ฉันตัวอย่างคำถาม .. : D
Khairil Ushan

ดูที่ Joda Time เพื่อเปรียบเทียบในโค้ด ( joda-time.sourceforge.net ) และใช้การเปรียบเทียบแบบยาวอย่างง่ายใน SQL (เช่นการเปรียบเทียบเชิงตัวเลข)
Syntax

เลือก * จากตารางที่สร้างระหว่าง a และ b;
koem
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.