如何存储每行具有可变数量属性的Android数据库

时间:2015-02-20 23:40:13

标签: android database sqlite

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

name,date,attr1,attr2,attr3,...

这些是要求:

  1. 每个日期只能包含一次名称
  2. 每个名称
  3. 可以有可变数量的属性(数字)
  4. 每个特定名称具有相同数量的属性
  5. 该应用将用于全天跟踪事件。事件可以包含零个或多个数字属性。

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

2 个答案:

答案 0 :(得分:3)

  

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

这取决于许多其他因素,例如如何查询和使用数据,交易量,数据增长和保留等。尽管如此,SQLite是一个很棒的选择,提供开箱即用的功能,可直接支持您的一些要求,并且通常用于此类情况。

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

  

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

让我们逐步完成每个列举的要求......

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

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

    UNIQUE(name, date)

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

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

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

这是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中迭代并处理这些结果。如果您的结果包含多个名称和/或日期,那么在循环中您应该跟踪上次使用的名称和日期。如果当前记录中的名称/日期相同,则该属性属于当前记录。如果名称/日期不同,那么这是一个新的。

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

另请注意,FOREIGN KEY表上存在attrs约束,这意味着如果您尝试使用name_id中的names将该记录插入该表中{1}}表,将在运行时抛出SQLiteConstraintException。您需要在Java代码中处理此异常。

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

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

  

还有哪些方法可以存储此类数据?

平面文件,JSON,XML,第三方数据存储(使用自己的库),仅举几例。

答案 1 :(得分:1)

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