- การเพิ่ม
STRICT ต่อท้ายคำจำกัดความของตารางช่วยป้องกันข้อผิดพลาดด้านชนิดข้อมูล เช่น ข้อความใด ๆ ถูกใส่ลงในคอลัมน์จำนวนเต็ม ได้ตั้งแต่เนิ่น ๆ และช่วยเพิ่ม ความสมบูรณ์ของข้อมูล
- แม้จะตรวจสอบชนิดข้อมูลตอนแทรกและอัปเดต แต่ค่าที่แปลงได้โดยไม่สูญเสียข้อมูล เช่น
'123' จะยังได้รับอนุญาต และชนิดของคอลัมน์ถูกจำกัดไว้ที่ INT, INTEGER, REAL, TEXT, BLOB, ANY
- สำหรับคอลัมน์ที่ต้องเก็บหลายชนิดข้อมูล สามารถระบุเป็น
ANY ได้ ทำให้ใช้ทั้งการตรวจสอบที่เข้มงวดและการจัดเก็บที่ยืดหยุ่นในตารางเดียวกันได้
- ไม่สามารถเปลี่ยนตารางเดิมให้เป็น STRICT ได้โดยตรง จึงต้อง สร้างตารางใหม่และคัดลอกข้อมูล และข้อมูลเดิมที่ผิดพลาดต้องถูกจัดระเบียบหรือแปลงชนิดข้อมูลก่อน
- ตาราง STRICT รองรับเฉพาะใน SQLite 3.37.0 ขึ้นไป และแม้ในเชิงทฤษฎีจะมีต้นทุนจากการตรวจสอบ แต่การทดลองแบบไม่เป็นทางการไม่พบความแตกต่างด้านประสิทธิภาพหรือขนาดไฟล์อย่างชัดเจน
การสร้างตาราง STRICT
- ตาราง STRICT ของ SQLite ใช้การตรวจสอบชนิดข้อมูลที่เข้มงวดขึ้น คล้ายกับเอนจิน SQL อื่น ๆ
- เพียงเติม
STRICT ไว้ท้ายคำจำกัดความ CREATE TABLE
CREATE TABLE people (name TEXT) STRICT;
การตรวจสอบชนิดข้อมูลในการแทรกและอัปเดต
- ตาราง SQLite ทั่วไปสามารถเก็บข้อความอย่าง
'garbage' ลงในคอลัมน์ INTEGER ได้ แต่ตาราง STRICT จะถือว่า ชนิดข้อมูลไม่ตรงกัน เป็นข้อผิดพลาด
CREATE TABLE people_nonstrict (age INTEGER);
INSERT INTO people_nonstrict (age) VALUES ('garbage');
-- 정상 처리됨
CREATE TABLE people_strict (age INTEGER) STRICT;
INSERT INTO people_strict (age) VALUES ('garbage');
-- 오류: cannot store TEXT value in INTEGER column
- การตรวจสอบแบบเดียวกันนี้ใช้กับ
UPDATE ด้วย จึงป้องกันชนิดข้อมูลที่ไม่ถูกต้องได้แม้ตอนเปลี่ยนค่าหลังบันทึกแล้ว
- อย่างไรก็ตาม หากค่าสามารถแปลงได้โดยไม่สูญเสียข้อมูล ตาราง STRICT ก็ยังอนุญาต
- สตริง
'123' สามารถแปลงเป็นจำนวนเต็ม 123 ได้อย่างสมบูรณ์ ดังนั้นการแทรกสองรายการด้านล่างจึงถูกประมวลผลเหมือนกัน
INSERT INTO people_strict (age) VALUES ('123');
INSERT INTO people_strict (age) VALUES (123);
ข้อจำกัดด้านชนิดข้อมูลในขั้นตอนกำหนดตาราง
- ในตารางทั่วไป สามารถใช้ชื่อชนิดข้อมูลที่ SQLite ไม่รองรับในการประกาศคอลัมน์ได้
GARBAGE, DATETIME, JSON, UUID, BLOBB ล้วนถูกยอมรับ
- การประกาศเช่นนี้อาจเกิดจากการพิมพ์ผิดหรือความเข้าใจผิดเกี่ยวกับ ชนิดข้อมูลที่ SQLite รองรับ
- ตาราง STRICT จะเกิดข้อผิดพลาดในขั้นตอนสร้าง หากใช้ชื่อชนิดข้อมูลที่ไม่รองรับ
CREATE TABLE tbl (name GARBAGE) STRICT;
CREATE TABLE tbl (name DATETIME) STRICT;
CREATE TABLE tbl (name JSON) STRICT;
CREATE TABLE tbl (name UUID) STRICT;
CREATE TABLE tbl (name BLOBB) STRICT;
- ชนิดคอลัมน์ที่อนุญาตมีเพียง
INT, INTEGER, REAL, TEXT, BLOB, ANY เท่านั้น
- ต้องระบุชนิดข้อมูลให้ทุกคอลัมน์ จึงไม่สามารถละเว้นชนิดข้อมูลเหมือน
CREATE TABLE tbl (name) ได้
คงความยืดหยุ่นด้วย ANY
- หากต้องเก็บข้อมูลที่มีชนิดไม่แน่นอน สามารถใช้คอลัมน์
ANY ได้
- แม้อยู่ในตาราง STRICT คอลัมน์
ANY ก็สามารถเก็บชนิดข้อมูลใด ๆ ได้ ทั้งจำนวนเต็ม ข้อความ จำนวนจริง BLOB ฯลฯ
CREATE TABLE tbl (value ANY) STRICT;
INSERT INTO tbl (value) VALUES (123);
INSERT INTO tbl (value) VALUES ('text');
INSERT INTO tbl (value) VALUES (12.34);
INSERT INTO tbl (value) VALUES (X'8647');
การย้ายตารางเดิม
- ไม่มีวิธีใช้
ALTER เพื่อเปลี่ยนตารางเดิมที่ไม่เข้มงวดให้เป็นตาราง STRICT ได้โดยตรง ดังนั้นการสร้างให้เข้มงวดตั้งแต่ต้นจึงง่ายกว่า
- หากต้องการแปลงตารางเดิม ต้องทำตามขั้นตอน สร้างตาราง STRICT ใหม่ → คัดลอกข้อมูล → แทนที่ตารางเดิม
CREATE TABLE new_people (name TEXT) STRICT;
INSERT INTO new_people SELECT * FROM people;
DROP TABLE people;
ALTER TABLE new_people RENAME TO people;
- หากข้อมูลเดิมมีชนิดผิด เช่น มีข้อความอยู่ในคอลัมน์จำนวนเต็ม อาจเกิดข้อผิดพลาดระหว่างการคัดลอก
- ก่อนย้ายข้อมูล อาจต้องจัดระเบียบข้อมูลหรือแปลงชนิดด้วย
CAST
- การใช้นโยบายให้เฉพาะตารางใหม่เป็น STRICT ก็ทำได้ แต่จะทำให้แต่ละตารางมี ระดับความเข้มงวดในการตรวจสอบ ต่างกัน และอาจคาดเดาพฤติกรรมได้ยากกว่ากรณีที่ทุกตารางผ่อนปรนเหมือนกัน
กรณีที่ชนิดข้อมูลแบบยืดหยุ่นเหมาะสม
- ทีมพัฒนา SQLite ได้สรุป ข้อดีของชนิดข้อมูลแบบยืดหยุ่น แยกไว้ และยกตัวอย่างกรณีที่พฤติกรรมเริ่มต้นมีประโยชน์
- การใช้งานที่ตารางไม่เข้มงวดอาจสมเหตุสมผลมีดังนี้
- ที่เก็บคีย์-ค่าแบบล้วน ๆ ที่เก็บหลายชนิดข้อมูลตามเดิม
- พื้นที่สำหรับเก็บคุณสมบัติอื่น ๆ ที่มีชนิดต่างกัน
- กรณีนำเข้า CSV ที่ไม่สะอาดโดยตรง และต้องรักษาแม้แต่ค่าที่ไม่ถูกต้องไว้โดยไม่ให้สูญหาย
- อย่างไรก็ตาม ชนิดข้อมูลที่ไม่คาดคิดอาจก่อให้เกิดบั๊กที่สังเกตได้ยาก ดังนั้นในตารางทั่วไป การให้เกิดข้อผิดพลาดทันทีจึงมักดีกว่าการอนุญาตแบบเงียบ ๆ
- ในซอร์สของ SQLite มี คอมเมนต์ที่เรียกตารางไม่เข้มงวดว่า
legacy ด้วย แต่ยากจะถือเป็นหลักฐานที่น่าเชื่อถือกว่าคู่มือทางการ
ความเข้ากันได้ของเวอร์ชัน
- ตาราง STRICT ถูกนำเข้ามาใน SQLite 3.37.0 ซึ่งเปิดตัวในเดือนพฤศจิกายน 2021
- SQLite เวอร์ชันก่อนหน้านี้ไม่สามารถใช้ตาราง STRICT ได้
- เวอร์ชันเก่าอ่านฐานข้อมูลที่มีตาราง STRICT อยู่ไม่ได้เช่นกัน
- หากสร้างตาราง STRICT ด้วย SQLite รุ่นใหม่ แล้วเปิดฐานข้อมูลเดียวกันด้วย SQLite 3.36.0 จะเกิดข้อผิดพลาด
ประสิทธิภาพและพื้นที่จัดเก็บ
- ตาราง STRICT มีการตรวจสอบชนิดข้อมูลเพิ่มเติมตอนแทรกและอัปเดต ดังนั้นในทางทฤษฎีอาจช้ากว่า
- ในการทดลองแบบไม่เป็นทางการที่แทรกหลายล้านแถวลงในตารางที่มี 100 คอลัมน์ คอมพิวเตอร์หลายเครื่องล้วนไม่พบ ความแตกต่างด้านประสิทธิภาพที่ชัดเจน
- ขนาดไฟล์ฐานข้อมูลบนดิสก์ก็เท่ากัน แต่เนื่องจากไม่ใช่เบนช์มาร์กอย่างละเอียด จึงอาจมีความแตกต่างที่ยังไม่ถูกพบ
- การป้องกันไม่ให้ค่าที่ไม่ตรงกับความชอบของคอลัมน์ (column affinity) ถูกบันทึกโดยไม่ได้ตั้งใจ อาจทำให้ประสิทธิภาพดีขึ้นแทนได้เช่นกัน แต่ยังไม่มีการตรวจสอบแยกต่างหาก
สิ่งที่ควรพิจารณาเมื่อนำไปใช้
- ตาราง STRICT ไม่ได้แก้ปัญหาข้อมูลทั้งหมด แต่ช่วยลดความผิดพลาดที่เกี่ยวข้องกับชนิดข้อมูลและเสริม ความสมบูรณ์ของข้อมูล
- โดยส่วนใหญ่ เพียงเพิ่ม
STRICT ในคำจำกัดความของตารางก็ใช้งานได้ จึงนำไปใช้ได้ง่าย
- สำหรับตารางทั่วไป ประโยชน์จากการตรวจสอบชนิดข้อมูลอย่างเข้มงวดมักมากกว่าภาระในการย้ายข้อมูล ความไม่เข้ากันกับเวอร์ชันเก่า และความยืดหยุ่นที่ถูกจำกัด
1 ความคิดเห็น
ความเห็นจาก Hacker News
เนื่องจาก SQLite ไม่มีฟีเจอร์
ALTERตารางเพื่อเปลี่ยนเป็น strict mode ได้ จึงต้องคัดลอกข้อมูลจากตารางแบบไม่ strict ไปยังตารางแบบ strict และจากจุดนี้เองจึงได้เพิ่มความสามารถในการแปลงไปกลับทั้งสองทางใน sqlite-utils 4.1ใน CLI ใช้ได้ด้วย
uvx sqlite-utils transform data.db mytable --strictและใน Python ใช้db.table("mytable").transform(strict=True)ดู release note ได้ที่ https://sqlite-utils.datasette.io/en/stable/changelog.html#v..., เอกสาร Python API ที่ https://sqlite-utils.datasette.io/en/stable/python-api.html#..., และเอกสาร CLI ที่ https://sqlite-utils.datasette.io/en/stable/cli.html#transfo...
https://sqlite.org/flextypegood.html อธิบายว่าทำไม flexible typing ถึงเป็นค่าเริ่มต้น และมีแนวโน้มว่าจะไม่เปลี่ยนในอนาคต แต่ก็ไม่ตรงกับประสบการณ์จริง
ต่างจากคำอธิบายที่ว่าแม้ใส่ชื่อลูกค้าลงใน
Customer.creditScoreซึ่งเป็นจำนวนเต็ม ก็ยังตรวจพบและแก้ไขได้ง่าย แต่ในความเป็นจริง แถวข้อมูลที่เสียหายนั้นกู้คืนได้ยาก และข้อมูลอาจหายไปหมดแล้วก็ได้และก็เห็นด้วยได้ยากมากกับตรรกะที่ว่าการตรวจชนิดข้อมูลแบบเข้มงวดจะกันได้แค่ข้อผิดพลาดที่หาได้ง่าย จึงกลับทำให้การตรวจจับและแก้บั๊กยากขึ้น
ใน Postgres มักจะเพิ่มการตรวจสอบและกลไกป้องกันให้มากที่สุดเท่าที่ทำได้ เพื่อจะได้ไม่ต้องมานั่งไล่หาข้อผิดพลาดที่ไม่ควรเกิดตั้งแต่แรกในภายหลัง
สิ่งนี้ดูเหมือนจะเป็นผลจากยุคสมัยที่ SQLite ถูกสร้างขึ้นและความเชื่ออันแรงกล้าของผู้เขียน มากกว่าจะเป็นหลักวิศวกรรมที่เคร่งครัด และหลังถูกวิจารณ์อย่างหนักก็ให้ความรู้สึกเหมือนพยายามหาเหตุผลอะไรมารองรับเพื่อยืนกรานจุดยืนเดิม
แม้ Postgres จะให้ความยืดหยุ่นที่ต้องการได้ผ่านชนิดข้อมูลอย่าง JSON หรือ HSTORE แต่การให้ผู้ใช้เลือกใช้เมื่อจำเป็น แทนที่จะบังคับให้การกำหนดชนิดแบบไร้ขีดจำกัดเป็นค่าเริ่มต้น ย่อมดีกว่าแทบทุกครั้ง
อยากให้ STRICT เป็นค่าเริ่มต้น
นอกจากจุดนี้แล้ว ผู้พัฒนา SQLite ก็เป็นคนที่ยอดเยี่ยมและสร้างเครื่องมือที่สุดยอดมาก
PRAGMA foreign_keys = ON;ปัญหาใหญ่กว่าคือสำหรับ strict table ไม่มี pragma ที่เทียบเท่ากัน ทำให้ต้องเติม
STRICTซึ่งไม่เป็นมาตรฐานลงในทุกCREATE TABLEมีการพิจารณา global STRICT pragma ด้วย แต่สุดท้ายก็ไม่ได้ทำจริง โดยดูข้อมูลที่เกี่ยวข้องได้ที่ https://sqlite.org/foreignkeys.html และ https://sqlite.org/forum/forumpost/1b9d073a37ca5998
เพื่อหลีกเลี่ยงกรณีที่ซอฟต์แวร์สำหรับ SQLite 3.53 อัปเกรดเป็น 3.54 แล้ว
CREATE TABLEกลับสร้าง strict table ขึ้นมาแบบกะทันหัน ทำให้เกิด error และระบบพังทั้งชุดเลยชวนให้สงสัยว่าช่วงหนึ่ง SQLite อาจรองรับแค่ไวยากรณ์ foreign key แต่ยังไม่ได้ลงมือทำฟังก์ชันจริงหรือไม่
เคยต้องจัดการโค้ดที่ถูก deploy ไปยังอุปกรณ์หลายพันเครื่อง ซึ่งเก็บสตริง
'1'และ'0'ลงในคอลัมน์ boolean และการตามเก็บกวาดเรื่องนี้ก็ไม่สนุกเลยอีกทั้งยังไม่มีชนิดข้อมูล timestamp ทำให้ต้องเก็บในคอลัมน์ข้อความ และแม้แต่ฟังก์ชันวันที่/เวลามาตรฐานก็ยังสร้าง
yyyy-mm-dd HH:MM:SSที่ต้องตีความเองโดยปริยายว่าเป็น UTC แทนyyyy-mm-ddTHH:MM:SSZซึ่งเป็นรูปแบบ ISOSQLite เป็นโปรเจ็กต์ที่ยอดเยี่ยมจริง ๆ แต่การตัดสินใจด้านการออกแบบบางอย่างก็น่าฉงน
จากมุมมองของสภาพแวดล้อม SQL สำหรับองค์กร เดิมทีผมไม่เคยมอง SQLite อย่างจริงจังเพราะมันไม่ได้บังคับชนิดข้อมูลของฟิลด์โดยปริยาย และก็ยังแปลกใจตอนที่มันกลายเป็นฐานของเมตาดาตาในแอปสมาร์ตโฟน
มันทำให้นึกถึงเรื่องเล่าเก่า ๆ ในโลกเครือข่ายที่เลือกใช้ UDP เพราะ latency ต่ำและเรียบง่าย แล้วสุดท้ายก็ต้องกลับไปสร้าง ความน่าเชื่อถือแบบ TCP เองในระดับแอปพลิเคชันเกือบทั้งหมด
แต่การไปทำ type checking เองบน SQLite ที่ไม่ strict ดูแล้วไม่น่าจะได้ข้อดีแบบเดียวกัน
PostgreSQL ก็เช่นกัน ค่าเริ่มต้นถูกตั้งมาเผื่อเครื่องสเปกต่ำ ดังนั้นถ้าจะรีดประสิทธิภาพสูงสุดก็ยังต้องปรับแต่ง
อีกอย่าง TCP เป็นแบบ stream-based จึงมีปัญหา HOL blocking ในหลายแอปพลิเคชัน และถ้าคุณสร้าง reliability layer เองบน UDP ก็มีโอกาสได้ผลลัพธ์ที่ดีกว่า TCP หลังจากลงแรงไปมาก
เพราะคนเหล่านั้นจะบอกว่ามันเสียงดังและบังคับยาก ทั้งที่จริง ๆ แล้วมันถูกออกแบบมาเพื่อการใช้งานอีกแบบ แต่กลับถูกตัดสินจาก use case ของคนวิจารณ์เอง
ตารางแบบ strict มีข้อเสียตรงที่ ใช้บางชนิดข้อมูลอย่าง Date ไม่ได้ แต่ถึงอย่างนั้นมันก็ควรเป็นค่าเริ่มต้น
ถ้ามีหลายแอปพลิเคชันใช้ฐานข้อมูลร่วมกัน ก็ควรเชื่อถือชนิดข้อมูลที่ประกาศไว้ได้ และถ้าแอปหนึ่งเก็บสตริงลงในคอลัมน์ตัวเลข แอปที่เหลือก็พังหมด
ในทางกลับกัน กรณีใช้งานหลักของ SQLite คือฐานข้อมูลแบบ embedded ซึ่งมักมีแอปเดียวใช้ จึงมีข้อดีตรงที่สามารถค่อย ๆ พัฒนาสคีมาได้แทนที่จะต้องสร้างฐานข้อมูลใหม่แล้วคัดลอกข้อมูล
ในกรณีนี้ โค้ดของแอปพลิเคชันย่อมรู้อยู่แล้วว่าควรคาดหวังอะไรจากแต่ละคอลัมน์ แม้จะมีชนิดข้อมูลปะปนกันก็ตาม
INTEGER,TEXT,BLOB,REAL,NUMERIC: https://sqlite.org/datatype3.htmlEXPLAINกับSELECTแบบใดก็ได้เพื่อดึงชื่อชนิดข้อมูลที่ระบุไว้ตามรูปแบบออกมาเพราะฉะนั้น ถึงจะใช้ชื่ออย่าง
DATEหรือDATETIMEก็ยังอนุมานสิ่งนั้นกลับมาไม่ได้ด้วยซ้ำDateไม่ใช่ชนิดข้อมูลจริง แต่เป็นเพียงคอลัมน์ที่มี numeric affinity เท่านั้นstrict mode จำกัดการเขียนชนิดคอลัมน์ ทำให้ใช้ชื่อที่มีความหมายมากกว่าไม่ได้ และยังทำให้โค้ดไม่สามารถอาศัยชื่อเหล่านั้นตอนแมปชนิดข้อมูลของฐานข้อมูลกับชนิดข้อมูลในแอปพลิเคชันได้ จึงกลับกลายเป็นว่าขัดขวางระบบชนิดข้อมูลที่เข้มงวดกว่าที่ชั้นแอปพลิเคชัน
รายละเอียดเพิ่มเติมอยู่ที่ https://hn.algolia.com/?query=chrismorgan+strict+sqlite&type=comment และถ้าคุณใช้งานฐานข้อมูลผ่าน crate อย่าง sqlx ของ Rust ก็มองว่าเลี่ยง strict mode จะดีกว่า
สำหรับฐานข้อมูลและ RPC นั้นผมต้องการ strict typing แต่ SQLite มีเป้าหมายการใช้งานต่างออกไปบ้าง และถ้าลองใช้เอง คุณอาจเข้าใจ https://sqlite.org/flextypegood.html มากขึ้น
ตัวอย่างเช่น การตั้งเป้าให้สคริปต์ใด ๆ ที่ไม่ได้เขียนมาเพื่อ SQLite โดยเฉพาะยังพอทำงานได้โดยบังเอิญ เป็นคุณสมบัติที่ DBMS อื่น ๆ ปกติไม่ได้คำนึงถึง
ข้อดีหลักของการกำหนดชนิดข้อมูลแบบยืดหยุ่นคือ ทำให้พัฒนาสคีมาได้ง่าย
เวลาความต้องการของฐานข้อมูลแบบ embedded เปลี่ยนไป ก็สามารถปรับสคีมาในที่เดิมได้ แทนที่จะต้องสร้างฐานข้อมูลใหม่และย้ายข้อมูล และถ้ามีแอปเดียวที่อ่านเขียนฐานข้อมูลอยู่แล้ว การมีสตริงเพิ่มเข้าไปในคอลัมน์จำนวนเต็มก็ไม่ใช่เรื่องน่าตกใจ
ในทางกลับกัน ถ้ามีหลายแอปพลิเคชันแชร์ฐานข้อมูลเดียวกันและอัปเดตตามตารางเวลาของตัวเอง สคีมาคือสัญญา ดังนั้นชนิดข้อมูลที่ผิดเพียงจุดเดียวก็อาจทำให้อีกแอปพังได้
ถ้าตารางที่แอปหนึ่งสร้างถูกอีกแอปนำไปใช้ ก็ต้องรักษาชนิดข้อมูลที่ตกลงกันไว้อย่างเคร่งครัด
การตรวจซ้ำตอนรันไทม์แทบไม่ได้ประโยชน์จริง เพราะโค้ดที่การวิเคราะห์แบบสถิตยืนยันแล้วว่าใส่สตริง จะไม่กลายพันธุ์ขึ้นมาจนใส่จำนวนเต็มเองโดยฉับพลัน
SQLite ต่างจาก Postgres ที่มีหลายแอปพลิเคชันแชร์ข้อมูลกันและต้องเชื่อถือบุคคลที่สาม
ในสภาพแวดล้อมแบบ Postgres การ ตรวจสอบตอนรันไทม์ เป็นสิ่งจำเป็น แต่ SQLite โดยพื้นฐานแล้วถูกออกแบบมาสำหรับแอปหนึ่งตัวกับฐานข้อมูลหนึ่งชุด จึงต้องเชื่อถือแค่โค้ดของตัวเองที่ประเมินได้ตั้งแต่ตอนคอมไพล์
ถ้าเป็นกรณีพิเศษที่มีหลายแอปแชร์ไฟล์เดียวกัน ก็สามารถเปิดใช้ตารางแบบ strict ได้
ชนิดข้อมูลแบบไดนามิกอาจเหมาะกับการใช้งานอย่าง key-value store แบบง่าย ๆ แต่ก็ควรถามว่าระหว่างการที่
INTEGERรับ'hello world'ได้โดยไม่ error กับการที่ต้องระบุคีย์เวิร์ดอย่างNONSTRICTหรือชนิดข้อมูลANYอย่างชัดเจนก่อนถึงจะใส่ค่าแบบนั้นได้ แบบไหนสอดคล้องกับ หลักการไม่ทำให้ผู้ใช้ประหลาดใจโดยไม่จำเป็น มากกว่ากันผู้ใช้ SQLite ส่วนใหญ่น่าจะไม่ได้คาดว่าจะเป็นแบบแรก
ซึ่งก็สอดคล้องกับคำอธิบายที่ว่าอยากให้โค้ดสำหรับ DBMS อื่นมารันบน SQLite ได้โดยบังเอิญ
ถึงอย่างนั้น ในเมื่อผู้ใช้ไม่ได้ละการระบุชนิดข้อมูล แต่เขียน
INTEGERไว้ชัดเจนแล้วกลับยังใส่ข้อความได้ นี่ก็ยังเป็นเรื่องน่าประหลาดใจมากเคยมีกรณีที่ UUID ซึ่งขึ้นต้นด้วยค่าอย่าง
08123…ถูก parse เป็นเลขฐานแปด ทำให้บางส่วนถูกแปลงเป็นตัวเลขผิดมันทั้งชวนสับสนและน่าหงุดหงิด แต่ก็แก้ได้ด้วยการใช้
STRICTแล้วสร้างตารางใหม่ทั้งหมดเพราะ SQLite ไม่มี ชนิดข้อมูลเลขฐานแปด
โดยพื้นฐานจะใช้
CREATE TABLE ... STRICT WITHOUT ROWIDและไม่รู้ว่ามีเหตุผลอะไรที่ต้องทำให้ต่างจากนี้เป็นพิเศษ