如何创建和规范化这个 SQL 关系数据库?

Posted

技术标签:

【中文标题】如何创建和规范化这个 SQL 关系数据库?【英文标题】:How to create and normalise this SQL relational database? 【发布时间】:2021-10-12 05:44:31 【问题描述】:

我正在尝试设计一个 SQL lite 数据库。我已经在纸上快速设计了我想要的东西。

到目前为止,我有一个包含以下列的表格:

user_id(是唯一的,也是表的主键) number_of_items_allowed(可以是任意数字,不必一定是 独一无二) list_of_items(任意大小的列表,只要小于等于 到 number_of_items_allowed 并且此列表存储项目 ID)

我最苦恼的专栏是list_of_items。我知道关系数据库没有允许列表的列,您必须使用该信息创建第二个表来规范化数据库。我查看了一些堆栈溢出答案,包括 this 一个,它表示您不能将列表存储在列中,但我无法将接受的答案应用于我的案例。

我曾考虑过有一个辅助表,其中每个项目 ID 都有一行属于 user_id,在这种情况下主键将是项目 ID 和 user_id 的组合,但是,我不确定这是否是理想的解决方法。

【问题讨论】:

我不会有一个列list_of_items,我肯定更喜欢另一个具有 userID 和 itemID 复合唯一索引的表。不需要主键,尽管您可以有一个,只要其他两列是唯一的复合索引以避免重复。 【参考方案1】:

考虑以下具有 3 个表的架构:

CREATE TABLE users (
  user_id INTEGER PRIMARY KEY, 
  user TEXT NOT NULL,
  number_of_items_allowed INTEGER NOT NULL CHECK(number_of_items_allowed >= 0)
);

CREATE TABLE items (
  item_id INTEGER PRIMARY KEY, 
  item TEXT NOT NULL
);

CREATE TABLE users_items (
  user_id INTEGER NOT NULL REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE CASCADE, 
  item_id INTEGER NOT NULL REFERENCES items (item_id) ON UPDATE CASCADE ON DELETE CASCADE, 
  PRIMARY KEY(user_id, item_id)
);

对于此架构,您需要在 users_items 上使用 BEFORE INSERT 触发器,该触发器通过将用户的 number_of_items_allowed 与用户当前拥有的项目数进行比较来检查是否可以为用户插入新项目:

CREATE TRIGGER check_number_before_insert_users_items 
BEFORE INSERT ON users_items
BEGIN
   SELECT
     CASE
       WHEN (SELECT COUNT(*) FROM users_items WHERE user_id = NEW.user_id) >=
            (SELECT number_of_items_allowed FROM users WHERE user_id = NEW.user_id)
         THEN RAISE (ABORT, 'No more items allowed')
     END;
END;

如果新值小于该用户的当前项目数,您将需要另一个触发器来检查 number_of_items_allowed 何时更新:

CREATE TRIGGER check_number_before_update_users 
BEFORE UPDATE ON users
BEGIN
   SELECT
     CASE
       WHEN (SELECT COUNT(*) FROM users_items WHERE user_id = NEW.user_id) > NEW.number_of_items_allowed
         THEN RAISE (ABORT, 'There are already more items for this user than the value inserted')
     END;
END;

请参阅demo。

【讨论】:

谢谢。我已经使用了您的数据库并对其进行了更新以允许信用到期,这可以在this fiddle 上看到。你知道我为什么会出错吗? @knowledge_seeker 这可能是小提琴的错误。这里:dbfiddle.uk/… 没有错误。

以上是关于如何创建和规范化这个 SQL 关系数据库?的主要内容,如果未能解决你的问题,请参考以下文章

sql怎么设置外键

SQL_关系数据库管理系统(RDBMS)概念

SQL Server讲课笔记04:创建与管理数据库

如何在关系数据库中使用Elasticsearch

Python学哪个数据库

如何规范用户、引用和标签之间的(数据库)关系?