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 中遍历并处理这些结果。如果您的结果包括多个名称和/或日期,那么在您的循环中,您应该跟踪最后使用的名称和日期。如果当前记录中的姓名/日期相同,则该属性属于当前的。如果名称/日期不同,那么这是一个新的。
请注意,这种数据库设计方法很灵活,允许您查询属性,例如,查看关联的名称/日期对。
另请注意,attrs 表上有一个FOREIGN KEY 约束,这意味着如果您尝试将一条记录插入到该表中,并且该表中不存在names 表中不存在的name_id,则@ 987654326@ 将在运行时抛出。您需要在您的 java 代码中处理此异常。
- 每个特定名称具有相同数量的属性
您需要在您的 java 代码中满足此要求,可能在执行INSERT 之前对数据库进行一些检查。
还有哪些其他方式可以存储此类数据?
平面文件、JSON、XML、第三方数据存储(带有自己的库)等等。