如何创建和规范这个 SQL 关系数据库?
How to create and normalise this SQL relational database?
我正在尝试设计一个 SQL 精简版数据库。我已经在纸上快速设计了我想要的东西。
到目前为止,我有一个 table 包含以下列:
user_id
(也就是唯一的主键table)
number_of_items_allowed
(可以是任意数字,不一定是
唯一)
list_of_items
(任意大小的列表,只要小于等于
到 number_of_items_allowed 并且此列表存储项目 ID)
我最纠结的专栏是list_of_items
。我知道关系数据库没有允许列表的列,您必须使用该信息创建第二个 table 以规范化数据库。我查看了一些堆栈溢出答案,包括 this 一个,它说您不能将列表存储在列中,但我无法将已接受的答案应用到我的案例中。
我考虑过有一个辅助 table,它会为属于 user_id
的每个项目 ID 设置一行,在这种情况下,主键将是项目 ID 的组合和 user_id
,但是,我不确定这是否是理想的处理方式。
考虑以下包含 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。
我正在尝试设计一个 SQL 精简版数据库。我已经在纸上快速设计了我想要的东西。
到目前为止,我有一个 table 包含以下列:
user_id
(也就是唯一的主键table)number_of_items_allowed
(可以是任意数字,不一定是 唯一)list_of_items
(任意大小的列表,只要小于等于 到 number_of_items_allowed 并且此列表存储项目 ID)
我最纠结的专栏是list_of_items
。我知道关系数据库没有允许列表的列,您必须使用该信息创建第二个 table 以规范化数据库。我查看了一些堆栈溢出答案,包括 this 一个,它说您不能将列表存储在列中,但我无法将已接受的答案应用到我的案例中。
我考虑过有一个辅助 table,它会为属于 user_id
的每个项目 ID 设置一行,在这种情况下,主键将是项目 ID 的组合和 user_id
,但是,我不确定这是否是理想的处理方式。
考虑以下包含 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。