如何使用SQLite存储用户创建的列表?

问题描述

我正在尝试制作一个简单的应用程序,使用户可以列出他们想完成的电影/书籍的列表。创建列表后,他们可以添加到列表中,或对列表中的项目重新排序。

所以目前我有一个User表:

CREATE TABLE User (
    userid   INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,username TEXT    NOT NULL UNIQUE,password TEXT    NOT NULL,salt     TEXT    NOT NULL UNIQUE
);

还有一个列表表:

CREATE TABLE List (
    listid  INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,listname TEXT NOT NULL,userid INTEGER NOT NULL,date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,date_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,FOREIGN KEY(userid) REFERENCES User(userid)
);

我现在要弄清楚的是:如何存储实际列表?列表是用户创建的,用户应具有添加删除列表的能力,并且可以根据需要重新排序列表中的项目。我还想在每个列表项中存储一些元数据(例如电影各自的Wikipedia页面的URL)。

起初我以为,我将列表以JSON格式存储在列表表的一列中。但这在sql中似乎违反直觉。

快速搜索狂潮使我引起人们谈论联结表。我不确定我是否完全了解联结表。但这是否意味着用户每次创建一个新列表时,都必须为该列表中的所有项目生成一个新表? (因此,当我在List表中创建新行时,我还将创建链接到该行的新表ListItems_ListID_Username吗?)。

任何见识表示赞赏。如果不是很明显,那我就是sql的新手。 :)

编辑:作为一个例子,如果我将每个列表项存储在一个表中,我想每个列表项都将看起来像这个伪模式

(orderInList INTEGER,itemname TEXT,url TEXT (nullable),listid INTEGER (foreign key to List),userid INTEGER (foreignkey to User))

解决方法

这是否意味着每次用户创建一个新列表时,我都必须为该列表中的所有项目生成一个新表?

不!那是你最糟糕的事情。

项目是一个实体,因此只有一个表。然后,联结表将这些项目链接到列表。

在您的情况下,可能看起来像这样:

CREATE TABLE list
             (listid integer
                     NOT NULL
                     AUTOINCREMENT,userid integer
                     NOT NULL,...
              PRIMARY KEY (listid),FOREIGN KEY (userid)
                          REFERENCES user
                                     (userid));

CREATE TABLE item
             (itemid integer
                     NOT NULL
                     AUTOINCREMENT,...
              PRIMARY KEY (itemid));

CREATE TABLE listitem
             (listid integer
                     NOT NULL,itemid integer
                     NOT NULL,...
              PRIMARY KEY (listid,itemid),FOREIGN KEY (listid)
                          REFERENCES list
                                     (listid),FOREIGN KEY (itemid)
                          REFERENCES item
                                     (itemid));

因此,如果ID为1的用户拥有一个ID为1的列表,其中包含一个ID为1的项目,那么您将有一条记录

.________.________._____.
| listid | userid | ... |
+--------+--------+-----+
| 1      | 1      | ... |
'--------'--------'-----'

list中的一条记录

.________._____.
| itemid | ... |
+--------+-----+
| 1      | ... |
'--------'-----'

item和一条记录中

.________.________._____.
| listid | itemid | ... |
+--------+--------+-----+
| 1      | 1      | ... |
'--------'--------'-----'

listitem中。

但是(!)这里要记住一件事,以及为什么您可能不想使用该方法。 ID为2的用户也可以在ID为2的列表中包含此项目。

.________.________._____.
| listid | userid | ... |
+--------+--------+-----+
| 1      | 1      | ... |
+--------+--------+-----+
| 2      | 2      | ... |
'--------'--------'-----'

.________._____.
| itemid | ... |
+--------+-----+
| 1      | ... |
'--------'-----'

.________.________._____.
| listid | itemid | ... |
+--------+--------+-----+
| 1      | 1      | ... |
+--------+--------+-----+
| 2      | 1      | ... |
'--------'--------'-----'

如您所见,只有一项。如果任何一个用户对项目进行了更改,则另一个用户也将受到该更改的影响。现在在很多情况下这正是人们想要的。但是在您的情况下,您可能希望某个项目对于列表是唯一的,而不是全局的。即使书/电影是相同的,每个用户也可能希望拥有自己的记录,自己的笔记等。因此,您可能不希望连接表,而只希望项目表中的外键指向列表。

CREATE TABLE list
             (listid integer
                     NOT NULL
                     AUTOINCREMENT,listid integer
                     NOT NULL,...
              PRIMARY KEY (itemid),FOREIGN KEY (listid)
                          REFERENCES list
                                     (listid);

-- no table listitem

现在,一个项目正好属于一个列表,对该项目所做的任何更改将只影响该列表中的一个项目。

当然,您也可以使这些商品在全局范围内唯一,但不能由用户更改。为了使用户有机会在其列表中拥有自己的商品数据,可以在listitem中添加可以存储此信息的列。

,

您可以创建第三个表来存储特定用户拥有/创建的每个列表的项,如下所示:

CREATE TABLE Users(
  UserId INTEGER PK,UserName TEXT(n)
  .
  .
);

CREATE TABLE Lists(
  ListId INTEGER PK,ListName TEXT(n) NOT NULL,ListOwner INTEGER NOT NULL FK (UserId),CreationDate DATETIME NOT NULL,LastUpdate DATETIME NULL
);

CREATE TABLE ListItems(
  Id INTEGER PK,ListId INETGER FK,ItemName TEXT(n),ItemURL TEXT(n)
);