Sự khác biệt giữa các kiểu dữ liệu SQLite liên quan như INT, INTEGER, SMALLINT và TINYINT là gì?


101

Khi tạo một bảng trong SQLite3, tôi cảm thấy bối rối khi phải đối mặt với tất cả các kiểu dữ liệu có thể ngụ ý nội dung tương tự, vậy có ai có thể cho tôi biết sự khác biệt giữa các kiểu dữ liệu sau không?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

Có một số tài liệu ở đâu đó liệt kê min./max. dung lượng của các kiểu dữ liệu khác nhau? Ví dụ: tôi đoán smallintcó giá trị lớn nhất lớn hơn tinyint, nhưng giá trị nhỏ hơn số nguyên, nhưng tôi không biết những dung lượng này là gì.

Câu trả lời:


95

SQLiteVề mặt kỹ thuật, không có kiểu dữ liệu, có các lớp lưu trữ trong hệ thống nhập tệp kê khai và vâng, thật khó hiểu nếu bạn đã quen với các kiểu truyền thống RDBMS. Mọi thứ, trong nội bộ, được lưu trữ dưới dạng văn bản. Các kiểu dữ liệu được ép buộc / chuyển đổi thành các vị trí lưu trữ khác nhau dựa trên các mối quan hệ (kiểu dữ liệu khác nhau được gán cho các cột).

Điều tốt nhất mà tôi khuyên bạn nên làm là:

  1. Tạm thời quên mọi thứ bạn từng biết về các kiểu dữ liệu cơ sở dữ liệu độc lập

  2. Đọc liên kết trên từ SQLitetrang web.

  3. Loại bỏ các loại dựa trên lược đồ cũ của bạn và xem chúng sẽ ánh xạ vào SQLite

  4. Di chuyển tất cả dữ liệu vào SQLitecơ sở dữ liệu.

Lưu ý: Các giới hạn về kiểu dữ liệu có thể phức tạp, đặc biệt nếu bạn thêm khoảng thời gian, ngày tháng hoặc những thứ có tính chất đó vào SQL. SQLitecó rất ít chức năng tích hợp cho những thứ đó. Tuy nhiên, SQLitenó cung cấp một cách dễ dàng để bạn tạo các hàm tích hợp của riêng mình để thêm khoảng thời gian và những thứ có tính chất đó, thông qua sqlite3_create_functionhàm thư viện. Bạn sẽ sử dụng cơ sở đó thay cho các thủ tục được lưu trữ truyền thống.


1
Cảm ơn đã trả lời và liên kết. Điều này có nghĩa là tôi nên bám vào các loại văn bản cơ bản, số, số nguyên, thực, không? Có vẻ rất hạn chế đối với tôi, đặc biệt là đến từ nền tảng MSSQL, Foxpro và Oracle. Trân trọng.
Alan Harris-Reid

6
Tôi đồng ý với bạn, nó có vẻ hạn chế lúc đầu. Tuy nhiên, tôi nghĩ bạn sẽ thấy rằng SQLite rất tha thứ trong cách bạn đưa dữ liệu vào cơ sở dữ liệu thông qua hệ thống liên kết của nó. SQLite không độc lập - nó được thiết kế để trở thành một phần mềm phụ trợ cơ sở dữ liệu nhỏ mà bạn đặt trong các ứng dụng nhỏ để chỉ được truy cập thông qua một API truy cập cơ sở dữ liệu trong mã. Giải quyết các vấn đề trong SQLite thường là vấn đề tìm ra cách họ muốn bạn thực hiện.
J. Polfer

Tôi muốn gắn bó với các loại cơ bản.
J. Polfer

4
@Alan: Bạn có thể thấy hữu ích khi khai báo cột sở thích kiểu số là DATEhoặc BOOLEAN, nhưng tôi sẽ không bận tâm đến việc phân biệt giữa các kích thước khác nhau của số nguyên. Điều này đặc biệt đúng đối với trường hợp INTEGER PRIMARY KEY, một trường hợp mà tên loại chính xác quan trọng.
dan04

"Mọi thứ được lưu trữ dưới dạng văn bản" dường như là sai theo sqlite.org/fileformat.html , cho biết các số được lưu trữ dưới dạng biến thể nhỏ gọn / float64 và chỉ blob và văn bản được lưu trữ dưới dạng chuỗi
phiresky

47

Sự khác biệt là đường cú pháp. Chỉ một số chuỗi con của tên kiểu quan trọng như liên quan đến mối quan hệ của kiểu.

  • Mối quan hệ INT, INTEGER, SMALLINT, TINYINT → INTEGER, vì tất cả chúng đều chứa "INT".
  • LONGCHAR, LONGVARCHAR → TEXT ái lực, vì chúng chứa "CHAR".
  • DEC, DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, vì chúng không chứa bất kỳ chuỗi con nào quan trọng.

Các quy tắc để xác định mối quan hệ được liệt kê tại trang web SQLite .

Nếu bạn nhấn mạnh vào việc nhập nghiêm ngặt, bạn có thể triển khai nó với các CHECKràng buộc:

CREATE TABLE T (
   N   INTEGER CHECK(TYPEOF(N) = 'integer'),
   Str TEXT CHECK(TYPEOF(Str) = 'text'),
   Dt  DATETIME CHECK(JULIANDAY(Dt) IS NOT NULL)
);

Nhưng tôi không bao giờ bận tâm với nó.

Về công suất của từng loại:

  • INTEGERluôn luôn được ký 64-bit. Lưu ý rằng SQLite tối ưu hóa việc lưu trữ các số nguyên nhỏ phía sau, vì vậy, TINYINT sẽ không hữu ích.
  • REALluôn là 64-bit ( double).
  • TEXTBLOBkích thước tối đa được xác định bởi macro bộ xử lý trước, mặc định là 1.000.000.000 byte.

1
Bí quyết đẹp. Xin lưu ý rằng cách tiếp cận này yêu cầu giá trị cần chèn / cập nhật để có cùng lớp lưu trữ với lớp trong TYPEOF. Vì vậy, các nỗ lực để chèn một TEXT mà nếu không sẽ được chuyển đổi thành lớp lưu trữ NUMERIC / INTEGER bởi SQlite (nghĩa là, chuyển đổi như vậy là không mất dữ liệu theo sqlite.org/datatype3.html#affinity ) sẽ không thành công. Nói cách khác, cách tiếp cận này nghiêm ngặt hơn so với cách tiếp cận đặc biệt là chèn giá trị và sau đó xác thực bằng cách nào đó một cách kỳ diệu lớp lưu trữ được sử dụng để lưu trữ giá trị đó bằng SQLite. Để có cách tiếp cận dễ dãi hơn, hãy xem câu trả lời của tôi bên dưới.
eold

10

Hầu hết chúng đều có để tương thích. Bạn thực sự chỉ có số nguyên, float, text và blob. Ngày tháng có thể được lưu trữ dưới dạng số (thời gian unix là số nguyên, thời gian microsoft là float) hoặc dưới dạng văn bản.


Tôi đã sử dụng nó cho các dự án dựa trên web, nơi mà mọi thứ cuối cùng vẫn là văn bản được đưa vào một trang html. Tôi đã thực hiện rất nhiều chuyển đổi dữ liệu và chỉ sử dụng văn bản cho hầu hết các cột. Nó hoạt động tốt.
Jay

3

NULL. Giá trị là giá trị NULL.

INTEGER. Giá trị là một số nguyên có dấu, được lưu trữ trong 1, 2, 3, 4, 6 hoặc 8 byte tùy thuộc vào độ lớn của giá trị.

REAL. Giá trị là một giá trị dấu phẩy động, được lưu trữ dưới dạng số dấu phẩy động IEEE 8 byte.

TEXT. Giá trị là một chuỗi văn bản, được lưu trữ bằng cách sử dụng mã hóa cơ sở dữ liệu (UTF-8, UTF-16BE hoặc UTF-16LE).

BLOB. Giá trị là một khối dữ liệu, được lưu trữ chính xác như đầu vào.


1

Như một phần bổ sung cho câu trả lời từ dan04, nếu bạn muốn chèn một cách mù quáng NUMERICkhác với số 0 được đại diện bởi một TEXTnhưng đảm bảo rằng văn bản có thể chuyển đổi thành số:

your_numeric_col NUMERIC CHECK(abs(your_numeric_col) <> 0)

Trường hợp sử dụng điển hình là trong một truy vấn từ một chương trình coi tất cả dữ liệu là văn bản (để đồng nhất và đơn giản, vì SQLite đã làm như vậy). Điều thú vị về điều này là nó cho phép các cấu trúc như thế này:

INSERT INTO table (..., your_numeric_column, ...) VALUES (..., some_string, ...)

điều này thuận tiện trong trường hợp bạn đang sử dụng trình giữ chỗ vì bạn không phải xử lý đặc biệt các trường số khác 0 như vậy. Một ví dụ sử dụng sqlite3mô-đun của Python sẽ là,

conn_or_cursor.execute(
    "INSERT INTO table VALUES (" + ",".join("?" * num_values) + ")",   
    str_value_tuple)  # no need to convert some from str to int/float

Trong ví dụ trên, tất cả các giá trị trong str_value_tuplesẽ được thoát và được trích dẫn dưới dạng chuỗi khi được chuyển đến SQlite. Tuy nhiên, vì chúng tôi không kiểm tra rõ ràng kiểu thông qua TYPEOFmà chỉ có khả năng chuyển đổi sang kiểu , nên nó sẽ vẫn hoạt động như mong muốn (tức là SQLite sẽ lưu trữ dưới dạng số hoặc không thành công).

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.