数据类型/存储类在 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个存储类,分别是NULLINTEGERREALTEXTBLOB。但是,它还声明了 5 个关联,TEXTNUMERICINTEGERREALBLOB,它们并没有准确地映射到存储类。即,它没有NULL 亲和力,NUMERIC 在存储类中映射到什么?

    Decimal在C#中是一个浮点数,为什么要映射到NUMERICaffinity?那是因为REAL 最多有 8 个字节,而Decimal 有 16 个字节吗? SQLite 可以像在 C# 中一样存储 Decimal 吗?

    为什么BooleanDecimal 都映射到NUMERICBoolean 似乎占用了最小的存储空间(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 语句。虽然StringInt32 不是典型的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 中是不是重要?的主要内容,如果未能解决你的问题,请参考以下文章

Sqlite 使用

SQLite 3 中的数据类型

如何使用 android 中的 SQLite 扩展类在数据库中插入值?

SQLite -- 嵌入式关系型数据库

SQLite 中是不是可以进行十进制数约束?

SQLite剖析之数据类型