对于我的Android应用,我想使用以下格式的sqlite保存数据:
name,date,attr1,attr2,attr3,...
这些是要求:
该应用将用于全天跟踪事件。事件可以包含零个或多个数字属性。
问题是:sqlite是在这里存储东西的最佳方式吗?如果是这样,我如何设计我的数据库?还有哪些方法可以存储这类数据?
答案 0 :(得分:3)
是sqlite在这里存储东西的最佳方式吗?
这取决于许多其他因素,例如如何查询和使用数据,交易量,数据增长和保留等。尽管如此,SQLite是一个很棒的选择,提供开箱即用的功能,可直接支持您的一些要求,并且通常用于此类情况。
如果您对关系数据库没有太多经验,那么一开始实现此功能可能看起来很困难,但就像学习一门新语言或框架一样,随着时间的推移它会变得更容易。
如果是这样,我如何设计数据库?
让我们逐步完成每个列举的要求......
- 每个日期只能包含一次名称
醇>
SQLite支持UNIQUE
约束。例如,如果您的列名为name
和date
,则可以在CREATE TABLE
语句中添加以下内容:
UNIQUE(name, date)
(下面的示例中有一个更完整的CREATE TABLE
语句,它包含此约束。)
此约束可防止插入已存在的名称/日期对的行。使用android.database.sqlite.SQLiteDatabase
,如果您尝试使用重复的名称/日期对在表中插入行,则会在运行时抛出SQLiteConstraintException
。您需要在Java代码中处理此异常。
- 每个名称
可以有可变数量的属性(数字) 醇>
这是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代码中处理此异常。
- 每个特定名称具有相同数量的属性
醇>
您需要在java代码中满足此要求,可能在执行INSERT
之前在数据库中进行一些检查。
还有哪些方法可以存储此类数据?
平面文件,JSON,XML,第三方数据存储(使用自己的库),仅举几例。
答案 1 :(得分:1)
我不确定,但我认为实现您的要求的最佳方法是使用sqlite并解决您的问题,您只能拥有3列。一个用于名称,一个用于日期,另一个包含 JSON 数组,表示其余属性。