数据类型/存储类在 SQLite 中是不是重要?
Posted
技术标签:
【中文标题】数据类型/存储类在 SQLite 中是不是重要?【英文标题】:Does data type / storage class matter at all in SQLite?数据类型/存储类在 SQLite 中是否重要? 【发布时间】:2017-10-17 05:54:53 【问题描述】:我了解 SQLite 没有数据类型。但我不太确定创建表时是否重要?
我试图自动生成CREATE TABLE
语句。一开始,我以为我应该将 C# 数据类型映射到 SQLite 数据类型,直到我阅读了storage class 的描述。这份文件让我有些困惑,因此我认为最好问问并纠正我的理解。
说有5个存储类,分别是NULL
、INTEGER
、REAL
、TEXT
和BLOB
。但是,它还声明了 5 个关联,TEXT
、NUMERIC
、INTEGER
、REAL
和 BLOB
,它们并没有准确地映射到存储类。即,它没有NULL
亲和力,NUMERIC
在存储类中映射到什么?
Decimal
在C#中是一个浮点数,为什么要映射到NUMERIC
affinity?那是因为REAL
最多有 8 个字节,而Decimal
有 16 个字节吗? SQLite 可以像在 C# 中一样存储 Decimal
吗?
为什么Boolean
和Decimal
都映射到NUMERIC
? Boolean
似乎占用了最小的存储空间(1 字节甚至 1 位),但 Decimal
占用的空间更多。如果NUMERIC
是单字节类型,就不能存储Decimal
,或者如果是多字节,为什么不把Boolean
映射到INTEGER
呢?它应该更有效率,不是吗?或者,我应该完全忘记 SQLite 中数据类型的字节数吗?
尽管我脑海中有这些问题,但我尝试将struct
映射到表格中。部分示例代码如下(类/函数结构除外):
public sealed class ScreenInfo
public int ScreenId;
public string Name;
public int BoundX;
public int BoundY;
public int BoundW;
public int BoundH;
public int WorkingAreaX;
public int WorkingAreaY;
public int WorkingAreaW;
public int WorkingAreaH;
public int BitsPerPixel;
public bool IsPrimary;
public Rectangle Bounds
get return new Rectangle(BoundX, BoundY, BoundW, BoundH);
set BoundX = value.X; BoundY = value.Y; BoundW = value.Width; BoundH = value.Height;
public Rectangle WorkingArea
get return new Rectangle(WorkingAreaX, WorkingAreaY, WorkingAreaW, WorkingAreaH);
set WorkingAreaX = value.X; WorkingAreaY = value.Y; WorkingAreaW = value.Width; WorkingAreaH = value.Height;
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE `Screens` (`id` INTEGER PRIMARY KEY AUTOINCREMENT");
var fields = typeof(ScreenInfo).GetFields();
foreach (var f in fields)
sb.Append($", `f.Name` Type.GetTypeCode(f.FieldType).ToString()");
sb.Append(");");
上面的代码生成以下 SQL 语句。虽然String
和Int32
不是典型的SQL 数据类型,但它似乎工作正常。
"CREATE TABLE `Screens` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `ScreenId` Int32, `Name` String, `BoundX` Int32, `BoundY` Int32, `BoundW` Int32, `BoundH` Int32, `WorkingAreaX` Int32, `WorkingAreaY` Int32, `WorkingAreaW` Int32, `WorkingAreaH` Int32, `BitsPerPixel` Int32, `IsPrimary` Boolean);"
如果struct不包含名为id
的字段(否则会与主键冲突),是否会导致SQLite数据库出现其他潜在问题?
提前致谢!
【问题讨论】:
【参考方案1】:SQLite确实有数据类型,它只是使用动态类型,也就是说,它不限制可以插入到列中的类型。
关联不是存储类;它们描述了列“想要”的类型。因此,不存在 NULL 亲和性。
NUMERIC 相似性映射到 INTEGER 或 REAL,哪个更有效。
SQLite 没有十进制类型。
SQLite 的存储类是类型,但the actual way how values are stored in the database 不同。整数可以小于 8 个字节,布尔值占 0 个字节。
将列类型写入Int32
不会使其与映射到 INTEGER 亲和性的任何其他类型有任何不同;它仅对文档有用。
【讨论】:
谢谢。我可以肯定地说我可以在CREATE TABLE
中使用任何列类型,而“正确”类型的唯一用途是让开发人员更轻松地读取数据库?
亲和力可以稍微改变行为。
谢谢。刚刚发现一篇关于亲和力的新文章。它说如果将“0”存储到 INTEGER 亲和力,它将转换为数字 0,但在 TEXT 亲和力中它将保留“0”。使用其中任何一个有什么好处(精度/性能)吗?如何在插入时声明无关联?例如:CREATE TABLE Screens (id INTEGER PRIMARY KEY AUTOINCREMENT, ScreenId, Name, BoundX, ...
您链接到的文档解释了具有和不具有关联性的列的行为方式。您可以使用任何结果来实现您想要的行为。以上是关于数据类型/存储类在 SQLite 中是不是重要?的主要内容,如果未能解决你的问题,请参考以下文章