Tìm hiểu cách làm việc với hệ thống kiểu động của SQLite và sử dụng các tính năng như affinity kiểu, lớp lưu trữ và chế độ STRICT để tăng tính toàn vẹn dữ liệu.
SQLite sử dụng một hệ thống kiểu linh hoạt dựa trên các lớp lưu trữ và affinity kiểu. Khác với các RDBMS truyền thống áp dụng kiểu nghiêm ngặt, SQLite cho phép xử lý kiểu dữ liệu linh động hơn. Hiểu mô hình này rất quan trọng để đảm bảo tính nhất quán dữ liệu và tránh các lỗi khó phát hiện trong logic ứng dụng.
Trong bài viết này, tôi sẽ khám phá hệ thống kiểu của SQLite và chỉ cho bạn cách làm việc với các kiểu dữ liệu phổ biến trong SQLite. Nếu bạn mới học SQL, hãy bắt đầu với khóa học Introduction to SQL của chúng tôi để xây nền tảng vững chắc. Ngoài ra, tôi thấy SQL Basics Cheat Sheet mà bạn có thể tải về là một tài liệu tham khảo hữu ích vì nó có hầu hết các hàm SQL thường dùng.
Các khái niệm cốt lõi của hệ thống kiểu trong SQLite
Để làm việc với SQLite, điều quan trọng là nắm được cách nó lưu trữ và diễn giải dữ liệu bên trong. Bên dưới, tôi sẽ giải thích cách hệ thống kiểu của SQLite giúp thiết kế ứng dụng tin cậy và hiệu quả.
Giải thích về các lớp lưu trữ
SQLite sử dụng năm lớp lưu trữ để biểu diễn giá trị ở mức nội bộ:
NULL biểu thị giá trị thiếu hoặc không xác định.
INTEGER biểu thị số nguyên có dấu được lưu trong 1 đến 8 byte, tùy theo độ lớn.
REAL mô tả số dấu chấm động được lưu dưới dạng giá trị IEEE-754 8 byte.
TEXT lưu chuỗi văn bản được mã hóa theo UTF-8, UTF-16BE hoặc UTF-16LE.
BLOB lưu dữ liệu nhị phân đúng như đầu vào, không có chuyển đổi nào.
Các lớp lưu trữ này khác với kiểu dữ liệu được khai báo trong lược đồ bảng. Một cột có thể được khai báo là VARCHAR(50) hoặc BOOLEAN, nhưng giá trị thực tế sẽ được lưu bằng một trong năm lớp lưu trữ dựa trên nội dung của nó. Sự tách biệt này mang lại cho SQLite tính năng động và dễ chấp nhận, nhưng cũng yêu cầu nhà phát triển chú ý đến việc kiểm tra dữ liệu và tính nhất quán kiểu trong mã ứng dụng.
Affinity kiểu và hành vi của cột
Affinity kiểu trong SQLite là kiểu được khuyến nghị gán cho một cột dựa trên kiểu dữ liệu đã khai báo. SQLite dùng các quy tắc sau để xác định affinity từ văn bản kiểu đã khai báo.
Các cột khai báo VARCHAR, CHAR hoặc TEXT nhận affinity TEXT.
Các kiểu như INT và INTEGER nhận affinity INTEGER.
Các khai báo như DECIMAL, NUMERIC hoặc BOOLEAN nhận affinity NUMERIC.
Các kiểu như REAL, FLOAT hoặc DOUBLE nhận affinity REAL.
Affinity mặc định là BLOB nếu không khai báo kiểu nào được nhận diện.
Ví dụ, một cột khai báo VARCHAR(100) sẽ có affinity TEXT, nghĩa là SQLite sẽ cố chuyển các giá trị sang văn bản khi lưu. Affinity này định hướng cách SQLite ép và lưu dữ liệu, nhưng không hạn chế việc lưu các kiểu khác trong cột đó.
Manifest typing và các hệ quả
SQLite sử dụng manifest typing, nghĩa là kiểu dữ liệu gắn với từng giá trị riêng lẻ, không phải với vùng chứa là cột. Điều này cho phép nhiều loại giá trị cùng tồn tại trong một cột. Chẳng hạn, một cột khai báo là INTEGER vẫn có thể chứa giá trị TEXT hoặc BLOB.
Manifest typing cho phép nhà phát triển chèn đa dạng kiểu dữ liệu mà không cần thay đổi lược đồ. Tuy nhiên, đánh đổi là nó có thể dẫn đến dữ liệu không nhất quán, sắp xếp khó lường và phụ thuộc nhiều hơn vào logic ứng dụng để áp đặt quy tắc kiểu.
Tôi khuyên bạn học khóa Database Design để nắm quản trị cơ sở dữ liệu, bao gồm tổ chức dữ liệu theo các kiểu khác nhau và quản lý cơ sở dữ liệu.
Làm việc với các kiểu dữ liệu phổ biến trong SQLite
Giờ hãy xem cách xử lý các kiểu dữ liệu phổ biến trong SQLite, như văn bản, số, boolean, ngày giờ và dữ liệu nhị phân.
Văn bản, số và boolean
Các khai báo dữ liệu thường dùng trong SQLite gồm TEXT, INTEGER, REAL, NUMERIC và BOOLEAN, nhưng giá trị được lưu dựa trên affinity kiểu chứ không phải kiểu nghiêm ngặt. Sau đây là các trường hợp sử dụng cho từng kiểu dữ liệu trong một lược đồ thực tế.
TEXT lưu chuỗi, phù hợp cho tên, email, URL và dữ liệu văn bản nói chung.
INTEGER lý tưởng cho số nguyên như bộ đếm, ID và mã, mang lại lưu trữ và sắp xếp hiệu quả.
REAL lưu số thực cho các phép đo, tiền tệ hoặc giá trị không nguyên.
Affinity NUMERIC bao phủ các giá trị khai báo là DECIMAL, BOOLEAN hoặc tương tự. Tùy theo giá trị, SQLite tìm cách lưu dưới dạng INTEGER hoặc REAL.
BOOLEAN không phải lớp lưu trữ gốc mà được mô phỏng bằng cách lưu 0 (FALSE) hoặc 1 (TRUE) dưới dạng giá trị INTEGER ở tầng bên dưới.
Tôi khuyến nghị dùng INTEGER cho boolean với các ràng buộc rõ ràng ở phía ứng dụng, còn NUMERIC phù hợp với các giá trị cần phân tích số linh hoạt.
Ngày, giờ và chiến lược xử lý thời gian
SQLite không có kiểu DATE hoặc DATETIME gốc, nhưng hỗ trợ các định dạng sau để lưu dữ liệu thời gian:
TEXT: Lưu ngày/giờ dưới dạng chuỗi ISO8601 như YYYY-MM-DD HH:MM:SS. Định dạng này dễ đọc với con người và tương thích với nhiều công cụ, nhưng có thể chậm hơn khi so sánh.
REAL: Lưu ngày dưới dạng số ngày Julius (số thực), hữu ích cho phép toán ngày và truy vấn phạm vi, nhưng khó đọc hơn.
INTEGER: Lưu Unix timestamp, số giây kể từ 1970-01-01. Hiệu quả về lưu trữ và so sánh số học nhanh, nhưng không dễ đọc.
Khi làm việc với dữ liệu thời gian, bạn có thể dùng các hàm: date(), time(), datetime(), julianday() và strftime() để phân tích, định dạng và chuyển đổi giữa các định dạng thời gian.
Trường hợp biên với nhị phân và số
SQLite cũng hỗ trợ dữ liệu nhị phân qua lớp lưu trữ BLOB. BLOB hữu ích để lưu ảnh, tệp hoặc bất kỳ dữ liệu không phải văn bản. Khi làm việc với kiểu BLOB, luôn dùng truy vấn tham số hóa hoặc binding để chèn BLOB. Bạn cũng có thể lưu nhị phân lớn ở ngoài và tham chiếu bằng đường dẫn hoặc băm.
Mặc dù SQLite có thể lưu số nguyên đến 8 byte (-2^63 đến 2^63-1), các giá trị vượt phạm vi này có thể bị chuyển ngầm sang kiểu dữ liệu REAL, làm mất độ chính xác. SQLite thiếu cơ chế ép chặt độ chính xác số thập phân, nên khi cần độ chính xác cho dữ liệu tài chính, hãy luôn dùng thư viện ngoài hoặc logic ứng dụng.
Áp đặt cấu trúc với bảng STRICT
Khác với hệ thống kiểu linh hoạt truyền thống, SQLite đã giới thiệu bảng STRICT từ phiên bản 3.37.0. Một bảng STRICT cung cấp chế độ kiểu nghiêm ngặt, buộc giá trị cột phải khớp chính xác với kiểu khai báo. Khi bạn khai báo bảng là STRICT, mọi giá trị chèn vào phải khớp với kiểu của cột, sai lệch sẽ gây lỗi.
Chế độ STRICT cải thiện tính nhất quán và kiểm tra dữ liệu. Nó cũng giúp phát hiện sớm lỗi liên quan đến kiểu trong quá trình phát triển và khiến hành vi của SQLite dễ dự đoán hơn, gần với các RDBMS truyền thống.
Trước khi dùng STRICT với tư cách nhà phát triển, bạn cần lưu ý nó chỉ có từ SQLite 3.37.0 trở lên. Ngoài ra, bạn không thể trộn STRICT và manifest typing trong cùng một bảng.
Cân nhắc về hiệu năng và thiết kế
Hệ thống kiểu linh hoạt của SQLite có tác động đến hiệu năng. SQLite dùng mã hóa độ dài biến cho các giá trị INTEGER và REAL, nghĩa là số nhỏ hơn dùng ít byte hơn. Điều này giúp giảm kích thước cơ sở dữ liệu, đặc biệt với tập dữ liệu lớn.
Affinity kiểu cũng ảnh hưởng đến cách giá trị được lưu và so sánh. Các kiểu không nhất quán trong một cột có thể làm giảm hiệu quả của chỉ mục, vì SQLite có thể phải thực hiện thêm chuyển đổi kiểu khi tra cứu, làm chậm truy vấn.
Hãy cân nhắc các chiến lược sau để thiết kế lược đồ và truy vấn hiệu quả.
Định nghĩa các cột với affinity rõ ràng và nhất quán để giảm chi phí ép kiểu.
Cân nhắc ép kiểu tường minh trong truy vấn khi cần chuyển đổi kiểu để đảm bảo hành vi nhất quán.
Dùng affinity INTEGER cho ID và bộ đếm số, REAL cho dữ liệu dấu chấm động, và TEXT cho chuỗi.
Tránh trộn lẫn kiểu dữ liệu trong cùng một cột để ngăn các hiện tượng lạ khi sắp xếp và so sánh.
Chuẩn hóa lược đồ để tránh ép kiểu dư thừa hoặc trùng lặp dữ liệu.
Dùng EXPLAIN QUERY PLAN để phân tích hiệu năng và tinh chỉnh truy vấn.
Ví dụ về kiểu dữ liệu SQLite với các mẫu lược đồ
Các lược đồ bảng sau minh họa việc sử dụng hợp lý kiểu dữ liệu, affinity kiểu và ràng buộc trong SQLite.
Bảng Users với mô phỏng boolean và ràng buộc
Trong ví dụ dưới đây:
is_active mô phỏng boolean bằng INTEGER với ràng buộc CHECK.
TEXT đảm bảo nhất quán cho giá trị chuỗi trong khi INTEGER dùng cho logic kiểu boolean.
-- Create users table with auto-incrementing rowid and enforce uniquenessCREATETABLE users (
id INTEGERPRIMARYKEY,
username TEXTNOTNULLUNIQUE,
email TEXTNOTNULL,
is_active INTEGERNOTNULLDEFAULT1CHECK(is_active IN(0,1))-- Simulates boolean);Được hỗ trợ bởi
Bảng Orders dùng dữ liệu thời gian và độ chính xác số
Trong truy vấn dưới đây, total dùng NUMERIC cho giá trị dạng tiền để xử lý độ chính xác ở phía ứng dụng. order_date được lưu dạng TEXT theo chuẩn ISO-8601, đảm bảo dễ đọc và tương thích với các hàm ngày.
-- Create orders table with row identifier and foreign key in practice-- ISO date format "YYYY-MM-DD"CREATETABLE orders (
order_id INTEGERPRIMARYKEY,
customer_id INTEGERNOTNULL,
total NUMERICNOTNULL,
order_date TEXTNOTNULLCHECK(length(order_date)=10));Được hỗ trợ bởi
Bảng Files với dữ liệu nhị phân và kiểm tra kiểu
Trong truy vấn dưới đây, content dùng BLOB để lưu dữ liệu nhị phân thô. uploaded_at lưu thời gian dưới dạng INTEGER để tiết kiệm không gian và tăng hiệu năng.
-- Create files table with raw binary data and Unix timestamp (epoch seconds)CREATETABLE files (
file_id INTEGERPRIMARYKEY,
name TEXTNOTNULL,
content BLOBNOTNULL,
uploaded_at INTEGERNOTNULL);Được hỗ trợ bởi
Bạn có thể kiểm tra kiểu lúc chạy bằng truy vấn sau:
SELECT typeof(uploaded_at), typeof(content)FROM files;Được hỗ trợ bởi
Hệ thống kiểu của SQLite linh hoạt hơn so với các RDBMS truyền thống như MySQL hoặc PostgreSQL. Bảng dưới đây so sánh SQLite với các cơ sở dữ liệu này.
Tính năng
SQLite
MySQL
PostgreSQL
Mô hình kiểu
Động (manifest typing, type affinity)
Nghiêm ngặt (nhưng có vài điểm lạ, như ép kiểu im lặng)
Nghiêm ngặt (áp đặt kiểu chặt chẽ)
Áp đặt kiểu khai báo
Không áp đặt (trừ khi dùng chế độ STRICT)
Chủ yếu được áp đặt, nhưng vẫn có chút linh hoạt
Áp đặt hoàn toàn
Xử lý Boolean
Mô phỏng như 0/1, TEXT, NUMERIC.
Có kiểu BOOLEAN (TRUE, FALSE)
Kiểu BOOLEAN gốc
Kiểu ngày/giờ
Lưu thủ công dạng TEXT, REAL hoặc INTEGER
Có kiểu ngày/giờ gốc
Kiểu thời gian gốc và phong phú
Độ nhạy của chỉ mục
Nhạy với việc trộn kiểu trong một cột
Đáng tin cậy nhờ hệ kiểu
Đáng tin cậy nhờ hệ kiểu
Tính linh hoạt lược đồ
Rất cao (mặc định ít ràng buộc)
Vừa phải
Cấu trúc và vững chắc
Di trú vào SQLite
Có thể cần nới lỏng áp đặt kiểu nghiêm ngặt
Nói chung suôn sẻ với một số điều chỉnh nhỏ
Có thể cần đơn giản hóa hoặc giảm độ chính xác
Di trú từ SQLite
Cần dọn dẹp dữ liệu và chuẩn hóa kiểu
Cần dữ liệu tuân thủ kiểu nghiêm ngặt hơn
Cần dữ liệu tuân thủ và lược đồ nghiêm ngặt hơn
Kết luận
SQLite có hệ thống kiểu linh hoạt mang lại nhiều lợi thế khi được sử dụng hợp lý. Bằng cách hiểu các lớp lưu trữ, affinity kiểu và manifest typing, nhà phát triển có thể thiết kế lược đồ cân bằng giữa khả năng thích ứng và độ tin cậy. Các tính năng như bảng STRICT, sử dụng kiểu nhất quán và chuẩn hóa giúp áp đặt cấu trúc khi cần.
Biên tập viên kỹ thuật về Khoa học dữ liệu với kinh nghiệm thực tế trong phân tích dữ liệu, trí tuệ doanh nghiệp và khoa học dữ liệu. Tôi viết nội dung thực tiễn, tập trung vào ngành về SQL, Python, Power BI, Databricks và kỹ thuật dữ liệu, dựa trên công việc phân tích trong thế giới thực. Bài viết của tôi kết nối chiều sâu kỹ thuật với tác động kinh doanh, giúp các chuyên gia chuyển đổi dữ liệu thành những quyết định vững chắc.
Câu hỏi thường gặp
Các lớp lưu trữ của SQLite là gì?⌄
Các lớp lưu trữ của SQLite gồm NULL, INTEGER, REAL, TEXT và BLOB.
Một cột có thể lưu nhiều kiểu dữ liệu không?⌄
Có. Trừ khi bảng được khai báo là STRICT, bất kỳ cột nào cũng có thể chứa các giá trị thuộc kiểu khác nhau.
Affinity kiểu trong SQLite là gì?⌄
Affinity kiểu là kiểu được khuyến nghị cho một cột dựa trên kiểu đã khai báo. SQLite cố gắng chuyển đổi giá trị chèn vào sang kiểu affinity của cột, nhưng không áp đặt nghiêm ngặt.
Giá trị BOOLEAN được xử lý thế nào trong SQLite?⌄
SQLite không có kiểu BOOLEAN riêng. Giá trị boolean thường được lưu dưới dạng INTEGER, 0 (FALSE) hoặc 1 (TRUE), sử dụng affinity NUMERIC.
Làm sao tôi kiểm tra một giá trị được lưu thế nào?⌄
Dùng hàm typeof() để kiểm tra lớp lưu trữ thực tế của một giá trị.
Đi kèm với các truy vấn luyện tập thực hành ở mọi bước, khóa học này dạy bạn mọi điều cần biết để phân tích dữ liệu bằng chính mã SQL của bạn ngay hôm nay!
SQLite sử dụng một hệ thống kiểu linh hoạt dựa trên các lớp lưu trữ và affinity kiểu. Khác với các RDBMS truyền thống áp dụng kiểu nghiêm ngặt, SQLite cho phép xử lý kiểu dữ liệu linh động hơn. Hiểu mô hình này rất quan trọng để đảm bảo tính nhất quán dữ liệu và tránh các lỗi khó phát hiện trong logic ứng dụng.
Trong bài viết này, tôi sẽ khám phá hệ thống kiểu của SQLite và chỉ cho bạn cách làm việc với các kiểu dữ liệu phổ biến trong SQLite. Nếu bạn mới học SQL, hãy bắt đầu với khóa học Introduction to SQL của chúng tôi để xây nền tảng vững chắc. Ngoài ra, tôi thấy SQL Basics Cheat Sheet mà bạn có thể tải về là một tài liệu tham khảo hữu ích vì nó có hầu hết các hàm SQL thường dùng.
Các khái niệm cốt lõi của hệ thống kiểu trong SQLite
Để làm việc với SQLite, điều quan trọng là nắm được cách nó lưu trữ và diễn giải dữ liệu bên trong. Bên dưới, tôi sẽ giải thích cách hệ thống kiểu của SQLite giúp thiết kế ứng dụng tin cậy và hiệu quả.
Giải thích về các lớp lưu trữ
SQLite sử dụng năm lớp lưu trữ để biểu diễn giá trị ở mức nội bộ:
NULLbiểu thị giá trị thiếu hoặc không xác định.INTEGERbiểu thị số nguyên có dấu được lưu trong 1 đến 8 byte, tùy theo độ lớn.REALmô tả số dấu chấm động được lưu dưới dạng giá trị IEEE-754 8 byte.TEXTlưu chuỗi văn bản được mã hóa theo UTF-8, UTF-16BE hoặc UTF-16LE.BLOBlưu dữ liệu nhị phân đúng như đầu vào, không có chuyển đổi nào.Kiểu dữ liệu SQLite. Nguồn ảnh: OpenAI
Các lớp lưu trữ này khác với kiểu dữ liệu được khai báo trong lược đồ bảng. Một cột có thể được khai báo là
VARCHAR(50)hoặcBOOLEAN, nhưng giá trị thực tế sẽ được lưu bằng một trong năm lớp lưu trữ dựa trên nội dung của nó. Sự tách biệt này mang lại cho SQLite tính năng động và dễ chấp nhận, nhưng cũng yêu cầu nhà phát triển chú ý đến việc kiểm tra dữ liệu và tính nhất quán kiểu trong mã ứng dụng.Affinity kiểu và hành vi của cột
Affinity kiểu trong SQLite là kiểu được khuyến nghị gán cho một cột dựa trên kiểu dữ liệu đã khai báo. SQLite dùng các quy tắc sau để xác định affinity từ văn bản kiểu đã khai báo.
Các cột khai báo
VARCHAR,CHARhoặcTEXTnhận affinityTEXT.Các kiểu như
INTvàINTEGERnhận affinityINTEGER.Các khai báo như
DECIMAL,NUMERIChoặcBOOLEANnhận affinityNUMERIC.Các kiểu như
REAL,FLOAThoặcDOUBLEnhận affinityREAL.Affinity mặc định là
BLOBnếu không khai báo kiểu nào được nhận diện.Ví dụ, một cột khai báo
VARCHAR(100)sẽ có affinityTEXT, nghĩa là SQLite sẽ cố chuyển các giá trị sang văn bản khi lưu. Affinity này định hướng cách SQLite ép và lưu dữ liệu, nhưng không hạn chế việc lưu các kiểu khác trong cột đó.Manifest typing và các hệ quả
SQLite sử dụng manifest typing, nghĩa là kiểu dữ liệu gắn với từng giá trị riêng lẻ, không phải với vùng chứa là cột. Điều này cho phép nhiều loại giá trị cùng tồn tại trong một cột. Chẳng hạn, một cột khai báo là
INTEGERvẫn có thể chứa giá trịTEXThoặcBLOB.Manifest typing cho phép nhà phát triển chèn đa dạng kiểu dữ liệu mà không cần thay đổi lược đồ. Tuy nhiên, đánh đổi là nó có thể dẫn đến dữ liệu không nhất quán, sắp xếp khó lường và phụ thuộc nhiều hơn vào logic ứng dụng để áp đặt quy tắc kiểu.
Tôi khuyên bạn học khóa Database Design để nắm quản trị cơ sở dữ liệu, bao gồm tổ chức dữ liệu theo các kiểu khác nhau và quản lý cơ sở dữ liệu.
Làm việc với các kiểu dữ liệu phổ biến trong SQLite
Giờ hãy xem cách xử lý các kiểu dữ liệu phổ biến trong SQLite, như văn bản, số, boolean, ngày giờ và dữ liệu nhị phân.
Văn bản, số và boolean
Các khai báo dữ liệu thường dùng trong SQLite gồm
TEXT,INTEGER,REAL,NUMERICvàBOOLEAN, nhưng giá trị được lưu dựa trên affinity kiểu chứ không phải kiểu nghiêm ngặt. Sau đây là các trường hợp sử dụng cho từng kiểu dữ liệu trong một lược đồ thực tế.TEXTlưu chuỗi, phù hợp cho tên, email, URL và dữ liệu văn bản nói chung.INTEGERlý tưởng cho số nguyên như bộ đếm, ID và mã, mang lại lưu trữ và sắp xếp hiệu quả.REALlưu số thực cho các phép đo, tiền tệ hoặc giá trị không nguyên.Affinity
NUMERICbao phủ các giá trị khai báo làDECIMAL,BOOLEANhoặc tương tự. Tùy theo giá trị, SQLite tìm cách lưu dưới dạngINTEGERhoặcREAL.BOOLEANkhông phải lớp lưu trữ gốc mà được mô phỏng bằng cách lưu0(FALSE) hoặc1(TRUE) dưới dạng giá trịINTEGERở tầng bên dưới.Tôi khuyến nghị dùng
INTEGERcho boolean với các ràng buộc rõ ràng ở phía ứng dụng, cònNUMERICphù hợp với các giá trị cần phân tích số linh hoạt.Ngày, giờ và chiến lược xử lý thời gian
SQLite không có kiểu
DATEhoặcDATETIMEgốc, nhưng hỗ trợ các định dạng sau để lưu dữ liệu thời gian:TEXT: Lưu ngày/giờ dưới dạng chuỗi ISO8601 nhưYYYY-MM-DD HH:MM:SS. Định dạng này dễ đọc với con người và tương thích với nhiều công cụ, nhưng có thể chậm hơn khi so sánh.REAL: Lưu ngày dưới dạng số ngày Julius (số thực), hữu ích cho phép toán ngày và truy vấn phạm vi, nhưng khó đọc hơn.INTEGER: Lưu Unix timestamp, số giây kể từ 1970-01-01. Hiệu quả về lưu trữ và so sánh số học nhanh, nhưng không dễ đọc.Khi làm việc với dữ liệu thời gian, bạn có thể dùng các hàm:
date(),time(),datetime(),julianday()vàstrftime()để phân tích, định dạng và chuyển đổi giữa các định dạng thời gian.Trường hợp biên với nhị phân và số
SQLite cũng hỗ trợ dữ liệu nhị phân qua lớp lưu trữ
BLOB. BLOB hữu ích để lưu ảnh, tệp hoặc bất kỳ dữ liệu không phải văn bản. Khi làm việc với kiểuBLOB, luôn dùng truy vấn tham số hóa hoặc binding để chèn BLOB. Bạn cũng có thể lưu nhị phân lớn ở ngoài và tham chiếu bằng đường dẫn hoặc băm.Mặc dù SQLite có thể lưu số nguyên đến 8 byte (
-2^63đến2^63-1), các giá trị vượt phạm vi này có thể bị chuyển ngầm sang kiểu dữ liệuREAL, làm mất độ chính xác. SQLite thiếu cơ chế ép chặt độ chính xác số thập phân, nên khi cần độ chính xác cho dữ liệu tài chính, hãy luôn dùng thư viện ngoài hoặc logic ứng dụng.Áp đặt cấu trúc với bảng STRICT
Khác với hệ thống kiểu linh hoạt truyền thống, SQLite đã giới thiệu bảng
STRICTtừ phiên bản 3.37.0. Một bảngSTRICTcung cấp chế độ kiểu nghiêm ngặt, buộc giá trị cột phải khớp chính xác với kiểu khai báo. Khi bạn khai báo bảng làSTRICT, mọi giá trị chèn vào phải khớp với kiểu của cột, sai lệch sẽ gây lỗi.Chế độ
STRICTcải thiện tính nhất quán và kiểm tra dữ liệu. Nó cũng giúp phát hiện sớm lỗi liên quan đến kiểu trong quá trình phát triển và khiến hành vi của SQLite dễ dự đoán hơn, gần với các RDBMS truyền thống.Trước khi dùng
STRICTvới tư cách nhà phát triển, bạn cần lưu ý nó chỉ có từ SQLite 3.37.0 trở lên. Ngoài ra, bạn không thể trộnSTRICTvà manifest typing trong cùng một bảng.Cân nhắc về hiệu năng và thiết kế
Hệ thống kiểu linh hoạt của SQLite có tác động đến hiệu năng. SQLite dùng mã hóa độ dài biến cho các giá trị
INTEGERvàREAL, nghĩa là số nhỏ hơn dùng ít byte hơn. Điều này giúp giảm kích thước cơ sở dữ liệu, đặc biệt với tập dữ liệu lớn.Affinity kiểu cũng ảnh hưởng đến cách giá trị được lưu và so sánh. Các kiểu không nhất quán trong một cột có thể làm giảm hiệu quả của chỉ mục, vì SQLite có thể phải thực hiện thêm chuyển đổi kiểu khi tra cứu, làm chậm truy vấn.
Hãy cân nhắc các chiến lược sau để thiết kế lược đồ và truy vấn hiệu quả.
Định nghĩa các cột với affinity rõ ràng và nhất quán để giảm chi phí ép kiểu.
Cân nhắc ép kiểu tường minh trong truy vấn khi cần chuyển đổi kiểu để đảm bảo hành vi nhất quán.
Dùng affinity
INTEGERcho ID và bộ đếm số,REALcho dữ liệu dấu chấm động, vàTEXTcho chuỗi.Tránh trộn lẫn kiểu dữ liệu trong cùng một cột để ngăn các hiện tượng lạ khi sắp xếp và so sánh.
Chuẩn hóa lược đồ để tránh ép kiểu dư thừa hoặc trùng lặp dữ liệu.
Dùng
EXPLAIN QUERY PLANđể phân tích hiệu năng và tinh chỉnh truy vấn.Ví dụ về kiểu dữ liệu SQLite với các mẫu lược đồ
Các lược đồ bảng sau minh họa việc sử dụng hợp lý kiểu dữ liệu, affinity kiểu và ràng buộc trong SQLite.
Bảng Users với mô phỏng boolean và ràng buộc
Trong ví dụ dưới đây:
is_activemô phỏng boolean bằngINTEGERvới ràng buộcCHECK.TEXTđảm bảo nhất quán cho giá trị chuỗi trong khiINTEGERdùng cho logic kiểu boolean.Bảng Orders dùng dữ liệu thời gian và độ chính xác số
Trong truy vấn dưới đây,
totaldùngNUMERICcho giá trị dạng tiền để xử lý độ chính xác ở phía ứng dụng.order_dateđược lưu dạngTEXTtheo chuẩn ISO-8601, đảm bảo dễ đọc và tương thích với các hàm ngày.Bảng Files với dữ liệu nhị phân và kiểm tra kiểu
Trong truy vấn dưới đây,
contentdùngBLOBđể lưu dữ liệu nhị phân thô.uploaded_atlưu thời gian dưới dạngINTEGERđể tiết kiệm không gian và tăng hiệu năng.Bạn có thể kiểm tra kiểu lúc chạy bằng truy vấn sau:
Tôi khuyên bạn học khóa Introduction to Relational Databases in SQL để tìm hiểu thêm về cấu trúc dữ liệu và cách tạo bảng trong cơ sở dữ liệu.
So sánh SQLite với các cơ sở dữ liệu khác
Hệ thống kiểu của SQLite linh hoạt hơn so với các RDBMS truyền thống như MySQL hoặc PostgreSQL. Bảng dưới đây so sánh SQLite với các cơ sở dữ liệu này.
Tính năng
SQLite
MySQL
PostgreSQL
Mô hình kiểu
Động (manifest typing, type affinity)
Nghiêm ngặt (nhưng có vài điểm lạ, như ép kiểu im lặng)
Nghiêm ngặt (áp đặt kiểu chặt chẽ)
Áp đặt kiểu khai báo
Không áp đặt (trừ khi dùng chế độ
STRICT)Chủ yếu được áp đặt, nhưng vẫn có chút linh hoạt
Áp đặt hoàn toàn
Xử lý Boolean
Mô phỏng như
0/1,TEXT,NUMERIC.Có kiểu
BOOLEAN(TRUE,FALSE)Kiểu
BOOLEANgốcKiểu ngày/giờ
Lưu thủ công dạng
TEXT,REALhoặcINTEGERCó kiểu ngày/giờ gốc
Kiểu thời gian gốc và phong phú
Độ nhạy của chỉ mục
Nhạy với việc trộn kiểu trong một cột
Đáng tin cậy nhờ hệ kiểu
Đáng tin cậy nhờ hệ kiểu
Tính linh hoạt lược đồ
Rất cao (mặc định ít ràng buộc)
Vừa phải
Cấu trúc và vững chắc
Di trú vào SQLite
Có thể cần nới lỏng áp đặt kiểu nghiêm ngặt
Nói chung suôn sẻ với một số điều chỉnh nhỏ
Có thể cần đơn giản hóa hoặc giảm độ chính xác
Di trú từ SQLite
Cần dọn dẹp dữ liệu và chuẩn hóa kiểu
Cần dữ liệu tuân thủ kiểu nghiêm ngặt hơn
Cần dữ liệu tuân thủ và lược đồ nghiêm ngặt hơn
Kết luận
SQLite có hệ thống kiểu linh hoạt mang lại nhiều lợi thế khi được sử dụng hợp lý. Bằng cách hiểu các lớp lưu trữ, affinity kiểu và manifest typing, nhà phát triển có thể thiết kế lược đồ cân bằng giữa khả năng thích ứng và độ tin cậy. Các tính năng như bảng
STRICT, sử dụng kiểu nhất quán và chuẩn hóa giúp áp đặt cấu trúc khi cần.Bước tiếp theo, tôi khuyên bạn học các khóa Exploratory Data Analysis in SQL và Data Manipulation in SQL để học cách phân tích dữ liệu thuộc các kiểu khác nhau bằng các truy vấn SQL nâng cao.