【问题标题】:how to store Android database with variable number of attributes per row如何以每行可变数量的属性存储Android数据库
【发布时间】:2015-02-21 15:10:05
【问题描述】:

对于我的 Android 应用,我想使用 sqlite 以这种格式保存数据:

姓名、日期、attr1、attr2、attr3、...

这些是要求:

  1. 每个日期只能包含每个名称一次
  2. 每个名称可以有可变数量的属性(数字)
  3. 每个特定名称具有相同数量的属性

该应用将用于全天跟踪事件。事件可以有零个或多个数字属性。

问题是:sqlite 是在这里存储东西的最佳方式吗?如果是这样,我该如何设计我的数据库?还有哪些其他方式可以存储此类数据?

【问题讨论】:

    标签: android database sqlite


    【解决方案1】:

    sqlite 是在这里存储东西的最佳方式吗?

    这将取决于许多其他因素,例如查询和使用数据的方式、事务量、数据增长和保留等。不过,根据您的描述,SQLite 是一个不错的选择,提供开箱即用的功能,直接支持您的某些要求,并且通常用于此类情况。

    如果您在关系数据库方面没有太多经验,实施此功能一开始可能看起来很困难,但就像学习一门新的语言或框架一样,随着时间的推移会变得更容易。

    如果是这样,我该如何设计我的数据库?

    让我们逐步了解您列举的每个需求...

    1. 每个日期只能包含每个名称一次

    SQLite 支持UNIQUE 约束。例如,如果您的列被命名为namedate,您可以在CREATE TABLE 语句中添加以下内容:

        UNIQUE(name, date)
    

    (更完整的 CREATE TABLE 语句在下面的下一个示例中,它包含此约束。)

    此约束防止插入已存在名称/日期对的行。使用android.database.sqlite.SQLiteDatabase,如果您尝试在表中插入具有重复名称/日期对的行,则会在运行时抛出SQLiteConstraintException。您需要在您的 java 代码中处理此异常。

    1. 每个名称可以有可变数量的属性(数字)

    这是normalizing 数据库的教科书案例,将您的数据放入多个表中。例如:

    CREATE TABLE names (
        name_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
        name TEXT NOT NULL,
        date DATETIME,
        UNIQUE(name, date));
    
    CREATE TABLE attrs (
        name_id INTEGER NOT NULL,
        attr_value INTEGER NOT NULL,
        FOREIGN KEY(attr_value) REFERENCES names(name_id));
    

    然后,您检索属性数据的查询将JOIN 这两个表。由于您指出“事件可以有零个或多个数字属性”,LEFT OUTER JOIN 可能是最合适的,因为即使没有属性,它也会返回名称和日期。

    这是一个示例查询,按名称:

    SELECT n.name, n.date, a.attr_value
    FROM names AS n
    LEFT OUTER JOIN attrs AS a 
        ON n.name_id = a.name_id
    WHERE n.name = 'SMITH'
    ORDER BY n.name, n.date, a.attr_value;
    

    此查询将返回如下结果:

    name              date         attr_value
    ---------------   ----------   ------------
    SMITH             2015-02-13   1027
    SMITH             2015-02-13   4426
    SMITH             2015-02-13   8390
    SMITH             2015-02-20   4426
    SMITH             2015-02-20   8152
    SMITH             2015-02-20   9328
    

    然后您可以在 java 中遍历并处理这些结果。如果您的结果包括多个名称和/或日期,那么在您的循环中,您应该跟踪最后使用的名称和日期。如果当前记录中的姓名/日期相同,则该属性属于当前的。如果名称/日期不同,那么这是一个新的。

    请注意,这种数据库设计方法很灵活,允许您查询属性,例如,查看关联的名称/日期对。

    另请注意,attrs 表上有一个FOREIGN KEY 约束,这意味着如果您尝试将一条记录插入到该表中,并且该表中不存在names 表中不存在的name_id,则@ 987654326@ 将在运行时抛出。您需要在您的 java 代码中处理此异常。

    1. 每个特定名称具有相同数量的属性

    您需要在您的 java 代码中满足此要求,可能在执行INSERT 之前对数据库进行一些检查。

    还有哪些其他方式可以存储此类数据?

    平面文件、JSON、XML、第三方数据存储(带有自己的库)等等。

    【讨论】:

      【解决方案2】:

      我不确定,但我认为满足您要求的最佳方法是使用 sqlite 并解决您的问题,您只能有 3 列。一个用于名称,一个用于日期,另一个包含代表其余属性的 JSON 数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-29
        • 1970-01-01
        • 2014-04-16
        • 1970-01-01
        • 2010-11-29
        • 2015-06-27
        • 2015-10-07
        相关资源
        最近更新 更多