在sqlite中创建一个表还是在多个表中创建更好?

时间:2019-01-02 19:30:41

标签: android sqlite android-sqlite

我正在用java创建一个使用sqlite存储数据的android应用程序。我要存储的数据是体育馆的实体,例如运动名称,设置,代表,体重和时间。

我在为所有练习创建一张桌子时还是遇到问题,或者每个练习都有一个像胸部卧推床桌子,倾斜卧推床桌子之类的桌子。

设计数据库为所有练习创建一个表还是每个练习都有自己的表是更好的选择吗?

允许用户动态创建表还不错吗? (因为当我允许用户动态创建表时,表的名称不应包含空格,而且我不知道如何解决此问题)

3 个答案:

答案 0 :(得分:0)

首先,您可以为您的应用程序绘制ER图,然后将其转换为表。表的数量取决于您的用例,但通常,一个应用程序中有多个表。尝试将数据库规范化规则应用于表。 https://en.wikipedia.org/wiki/Database_normalization

通常,不需要让用户创建表,您可以自己创建表并从用户获取数据(行)。

答案 1 :(得分:0)

规范化是数据库设计及其中表格的关键概念之一,即最小化/消除数据重复(尤其是文本数据,其存储和处理效率低下)。

所以基本上答案是,您应该有多个表,但,您实际上不应该真正基于每个用户动态分配表,单个用户表以及将用户映射到完成的练习是通常使用的方式。

  • 如果用户和/或练习的数量变得非常大(十个或十个千个),那么您可能需要考虑某种形式的分离。

从声音上来说,您有一个练习表,一个用户表,以及一个记录(记录)进行的练习的表,该表将映射到用户和练习。

作为示例,请考虑以下内容:-

DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS exercise;
DROP TABLE IF EXISTS log;

CREATE TABLE IF NOT EXISTS user (user_id INTEGER PRIMARY KEY, user_name TEXT, user_password TEXT);
CREATE TABLE IF NOT EXISTS exercise (exercise_id INTEGER PRIMARY KEY, exercise_name TEXT);
CREATE TABLE IF NOT EXISTS log (user_id_reference INTEGER, exercise_id_reference INTEGER, started TEXT DEFAULT CURRENT_TIMESTAMP, finished TEXT DEFAULT 0, repititions INTEGER, weight REAL);

INSERT INTO user (user_name, user_password) VALUES ('Fred','passwordFred'),('Mary','passwordMary'),('Linda','passwordLinda');

INSERT INTO exercise (exercise_name) VALUES ('Goblet Squat'),('Farmer''s Walk'),('Bent-Over Row'),('2 Armed Stiff-Legged DeadLift');

INSERT INTO log VALUES
    (2,3,'2018-12-31 10:30','2018-12-31 10:45',100,5.5),
    (2,1,'2018-12-31 10:50','2018-12-31 11:00',50,7.5),
    (2,3,'2019-01-01 10:25','2019-01-01 10:30',75,5.5),
    (1,1,'2018-12-30 09:00','2018-12-30 09:10',60,6.5),
    (1,1,'2018-12-31 09:00','2018-12-31 09:10',60,6.5),
    (1,1,'2019-01-01 09:00','2019-01-01 09:10',60,6.5);


SELECT sum(repititions * weight) AS workdone, user_name, exercise_name 
FROM log
JOIN exercise ON exercise.exercise_id = log.exercise_id_reference
JOIN user ON user.user_id = user_id_reference
GROUP BY user_id, exercise_id
ORDER BY user_name;

这将创建3个表:-

  1. 用户,获取用户特定的用户特定信息。
  2. 锻炼(每次锻炼)
  3. 日志,用于每次使用的每次锻炼。

    • 请注意,用户运动具有一个定义为类型INTEGER PRIMARY KEY id 列,该列具有特殊含义在SQLITE中的含义是,它使列成为特殊/通常隐藏的 rowid 的别名,并且id没有提供值,则该值将是该行的唯一标识符(第一个为1,下一个大概是2,依此类推)。这些是识别行的最有效方法,因此日志表使用它来引用用户和练习。

    • 日志是一些术语,用作映射/参考表,它促进了日志的多对多关系以及特定于日志的值,例如开始和结束的日期/时间,所使用的权重以及重复次数存储在日志中。

创建表后,将数据添加到3个表(3个用户,4个练习和一些日志条目)

最后,运行一个查询以累积权重*每个练习的每个用户的重复次数,作为将所有这些都捆绑在一起的示例。结果是:-

enter image description here

  • 总和被称为聚合函数。聚合函数将考虑每个组的所有值(由GROUP BY关键字定义)。对于 sum ,将为每个组将所有值加在一起。

  • JOIN 用于根据表达式(关系)组合表。

答案 2 :(得分:0)

标准化通常涉及考虑所有折衷。每次锻炼都有一张桌子可能会更清洁,但是您还必须考虑可能的缺点。您是否已经知道您的应用程序必须管理的完整练习清单?如果从一开始就进行了过多的练习,那么用户可能会不喜欢它,必须滚动很多以搜索正确的练习。另一方面,您可能不进行喜欢的练习而使用户失望。为每个人创建一张表格可能会迫使您经常更新您的应用,以增加或减少练习。如果您要询问用户定义的表,我猜您甚至在考虑让用户定义自己的练习的可能性。因此,固定数量的表可能会限制您的应用程序。

您可以创建具有通用名称(如exercise1,exercise2,...等)的表,然后使用映射表来联接锻炼名称和锻炼数据,但这可能很慢。

我建议您尝试使其尽可能地动态,但是为了防止性能问题,您应该粗略估计用户使用该应用程序可能会生成多少条记录,并制作一些小型测试应用程序来尝试不同的性能。设计(只需插入一些虚拟数据并在智能手机上运行一些查询)。