问题描述
我正在尝试制作一个简单的应用程序,使用户可以列出他们想完成的电影/书籍的列表。创建列表后,他们可以添加到列表中,或对列表中的项目重新排序。
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)
);