数据库设计 - 文章、博客文章、照片、故事

     2023-03-29     37

关键词:

【中文标题】数据库设计 - 文章、博客文章、照片、故事【英文标题】:Database design - articles, blog posts, photos, stories 【发布时间】:2011-06-25 13:03:06 【问题描述】:

我正在为一个网站设计一个数据库,该网站将至少表示 4 种不同的对象类型(文章、博客文章、照片、故事),每一种都有不同的足够数据要求来保证自己的表格。我们希望用户能够发布任何这些类型的 cmets。 cmets 的数据要求很简单,并且与评论所涉及的事物类型无关(即只是评论正文和作者的电子邮件)。

我想避免为 cmets 创建和管理 4 个以上的单独表的冗余,因此我希望能够将所有 cmets 保存在一个表中,可能通过 2 列指定关系:一列指定父级实体和一个用于父行 ID。

但我不明白我将如何实现外键,因为外键在 2 个和只有 2 个表之间建立关系(对吗?)。

那么考虑到所有这些,最好的方法是什么?

【问题讨论】:

【参考方案1】:

这是为您的应用实现超类型/子类型表的一种方法。

首先,超类型表。它包含所有子类型共有的所有列。

CREATE TABLE publications (
  pub_id INTEGER NOT NULL PRIMARY KEY,
  pub_type CHAR(1) CHECK (pub_type IN ('A', 'B', 'P', 'S')),
  pub_url VARCHAR(64) NOT NULL UNIQUE,
  CONSTRAINT publications_superkey UNIQUE (pub_id, pub_type)
);

接下来是几个子类型表。

CREATE TABLE articles (
  pub_id INTEGER NOT NULL,
  pub_type CHAR(1) DEFAULT 'A' CHECK (pub_type = 'A'),
  placeholder CHAR(1) NOT NULL, -- placeholder for other attributes of articles
  PRIMARY KEY (pub_id, pub_type),
  FOREIGN KEY (pub_id, pub_type) REFERENCES publications (pub_id, pub_type)
);

CREATE TABLE stories (
  pub_id INTEGER NOT NULL,
  pub_type CHAR(1) DEFAULT 'S' CHECK (pub_type = 'S'),
  placeholder CHAR(1) NOT NULL, -- placeholder for other attributes of stories
  PRIMARY KEY (pub_id, pub_type),
  FOREIGN KEY (pub_id, pub_type) REFERENCES publications (pub_id, pub_type)
);

这些子类型表中的 CHECK() 和 FOREIGN KEY 约束防止行在超类型中引用错误类型的行。它有效地在子类型之间划分 pub_id 值,保证任何给定的 pub_id 可以出现在一个且仅一个子类型表中。这就是为什么您需要对这对列 publications.pub_id, Publications.pub_type 使用 PRIMARY KEY 或 NOT NULL UNIQUE 约束。

cmets 的表格很简单。考虑到所有子类型都具有相同的结构,您可以引用超类型。

CREATE TABLE comments (
  pub_id INTEGER NOT NULL REFERENCES publications (pub_id),
  comment_timestamp TIMESTAMP NOT NULL DEFAULT now(),
  commenter_email VARCHAR(10) NOT NULL, -- Only allow people who have 
                                        -- really short email addresses
  comment_text VARCHAR(30) NOT NULL,    -- Keep 'em short!
  PRIMARY KEY (pub_id, comment_timestamp, commenter_email)
);

添加一点数据。

INSERT INTO publications VALUES
(1,'A', 'url 1 goes here'),
(2,'A', 'url 2 goes here'),
(3,'S', 'url 3 goes here');

INSERT INTO articles VALUES
(1,'A', 'A'),
(2,'A', 'B');

INSERT INTO stories VALUES
(3,'S', 'A');

INSERT INTO comments VALUES
(1, now(), 'a@b.com','You''re stupid'),
(1, now(), 'b@c.com', 'You''re stupid, too!');

现在您可以创建一个视图来显示所有文章并解决连接问题。你会为每个子类型做同样的事情。

CREATE VIEW articles_all AS
SELECT P.*, A.placeholder
FROM publications P
INNER JOIN articles A ON (A.pub_id = P.pub_id)

您可能更喜欢“published_articles”这样的名称,而不是“articles_all”。

要选择一篇文章及其所有 cmets,您只需左连接这两个表。 (但请看下面为什么你可能不会这样做。)

SELECT A.*, C.*
FROM articles_all A
LEFT JOIN comments C ON (A.pub_id = C.pub_id)
WHERE A.pub_id = 1;

您可能实际上不会为 Web 界面执行此操作,因为 dbms 必须返回文章的“n”个副本,其中“n”等于 cmets 的数量。但在某些应用程序中这样做确实有意义。在有意义的应用程序中,您会为每个子类型使用一个可更新视图,并且应用程序代码大部分时间都会使用可更新视图。


超类型/子类型更常见的业务应用涉及“Parties”(超类型)、“Organizations”和“Individuals”(子类型,非正式地公司人员. 地址,如上例中的“cmets”,与超类型相关,因为所有子类型(组织和个人)都有地址。

【讨论】:

@Snake:这不是一个坏主意,但连接不是必需的,您不需要动态 SQL。 (如果可能,动态 SQL 具有最好避免的风险。)“n”子类型的超类型/子类型设计映射到“n”+1 个基表和“n”视图。 “n”个视图中的每一个都将超类型表连接到子类型表之一;然后客户端使用视图,而不是基表。 (如有必要,编写触发器,让您通过视图执行 INSERT、UPDATE、DELETE。)一旦您有了一个命名良好、可更新的视图,您就不需要自己阅读该列。只是为了帮助 SQL 维护数据的完整性。 @Catcall:谢谢。清楚地了解视图的使用。我有点知道,但对这个问题的思考不够好。另一个问题:我的计划是依靠 Publications 表来生成 Pub_Id - 然后将其复制到子类型表中,因此每个表中的值都是唯一的,所以我不需要复合Publications 表上的主键。这有意义吗? @Snake:我明白你在说什么,但如果你使用的是 SQL dbms,你真的需要那个列和复合键。 CHAR(1) 列,在超类型和每个子类型中实现,并用作复合键和外键引用的一部分,保证超类型表中的每一行可以连接到一个且只有一个行子类型表。没有它,您可以在每个子类型表中插入相同的 pub_id,这使得超类型/子类型设计无用。 @CatCall:回到最后一个问题:鉴于 pubtype 在主键中的角色,是否有性能原因或其他原因将其保持为 1 个字符?如果是这样, int 会更好吗? (顺便说一句:感谢您的时间和耐心。请原谅我在这些事情上的“密度”。我的经验主要是前端,但这次我是一个人的项目;不过,幸运的是,我游说成功了花了很多时间,所以我可以仔细考虑。) @Snake: CHAR(1) 足够长,足够可读,而且它占用的空间比整数少。使用 CHAR(1) 可能会获得更好的性能,或者使用整数可能会获得更好的性能。但我通常更喜欢文字而不是数字,因为我发现阅读文字更容易。 (A) 文章、(B) 日志帖子、(S) 故事比 (1) 文章、(2) 博客文章、(3) 故事更容易记住。我不介意花时间;你不应该介意对我的每一个回复都投赞成票。还有我原来的答案。 ;)【参考方案2】:

您可以在数据库设计中使用超类型/子类型来避免该问题。为图像、视频、笔记创建超类型,然后链接到超类型。将所有公共列保留在超类型表中。

以下是几个与模型相似的问题/答案的链接:

One Two Three Four

【讨论】:

您的意思是为图像、视频笔记创建子类型而不是超类型?【参考方案3】:

在我看来,最好为 cmets 设置 4 个以上的单独表格。或者你可以有连接表。所有 cmets 的一张表...例如:博客表、评论表、blog_comment 表。这将允许您拥有外键。

Blog
--------
Blog_id
other fields

Blog_Comment
--------------
Blog_id
Comment_id


Comment
------------
Comment_id
other fields

【讨论】:

这是我推荐的设计。最后一种可能性(以及您是否需要这样的东西取决于您的设计)是在评论表或博客/视频/Etx 表中的每个条目中添加一个用户 ID,这样可以检索特定的所有 cmets用户(同样,如果这符合您的设计要求,并针对特定设计要求进行一些可能的调整......)。 USerID 的最终结果可能需要考虑一下。

博客页面设计(试水版)

...撰写页面1.博客主页面  列表编写思路    1.取出数据库中所有文章对象    2.将文章对象们打包成列表,传递到前端    3.前端页面把文章以标题超链接的形式逐个列出    4.模板For循环语法      %&nbs... 查看详情

用于博客的 mongodb 架构设计

...2011-07-1015:15:44【问题描述】:您将如何为具有基于文档的数据库(mongodb)的类似博客的网站设计架构。该站点具有以下对象:用户、文章、评论。用户可以在文章中添加评论。每个用户也可以对每个评论进行一次投票。我希望能够... 查看详情

网站开发(周二):项目需求分析

...实现HTML静态页面。最后,根据项目需求和业务流程进行数据库设计,由后端工程师构造数据库和开发网站后台。第一、从网站功能需求来看,博客功能分为:网站首页、文章分类页、文章搜索页、文章标签页、文章正文页。 ... 查看详情

博客网站设计

文章数据表:文章相关:   id  文章id       title 标题          Content 正文内容 作者相关: &nbs 查看详情

3-创建django博客的数据库模型(代码片段)

设计博客的数据库表结构博客最主要的功能就是展示我们写的文章,它需要从某个地方获取博客文章数据才能把文章展示出来,通常来说这个地方就是数据库。我们把写好的文章永久地保存在数据库里,当用户访问我... 查看详情

数据库设计案例

简单构建设计数据库简单构建设计数据库本文来自博客园,作者:Haziy,转载请注明原文链接:https://www.cnblogs.com/zhangyouren/p/16489363.html本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。博主的文章没有高度、... 查看详情

基于springboot的个人博客系统(源码+数据库)

...辑页面​7.后台文章管理列表页面五、文件组织结构六、数据库设计1. 文章详情表t_article2.文章评论表t_comment3.文章评论表t_statistic4.用户信息表t_user5.用户权限表authority6.用户权限关联表t_user_authority七、源码一、系统功能框架图... 查看详情

故事思维

? ?文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言、评论 查看详情

微信支付商户系统架构背后的故事

....com/community 李跃森,腾讯云PostgreSQL首席架构师,腾讯数据库团队架构师,负责微信支付商户系统核心数据库的架构设计和研发,PostgreSQL- 查看详情

storm项目:流数据监控1《设计文档…

博客公告: (1)本博客全部博客文章搬迁至《博客虫》http://blogchong.com/                     (2)文章相应的源代码下载链接參考博客虫站点 查看详情

博客随笔《文章目录》大纲

...分为三大部分,包括:前端开发技术、服务器开发技术、数据库开发技术*//-------------------------------------------------- 前端技术 -------------------------------------- 查看详情

基于javaee开发博客系统项目开发与设计(附源码)(代码片段)

...p、Servlet、Web三层架构、DButils服务器:Tomcat8.x.x;数据库:Mysql8.x.x开发环境:Win10系统+Idea开发+Maven构建2.项目模块3.项目效果博客首页博客分类博客标签博客归档博客数据详情博客管理后台博客管理博客发布... 查看详情

算法经典文章收藏

...apReduce实战--倒排索引-codingwu-博客园archimedesMapReduce原理与设计思想-codingwu-博客园archimedes算法--递推策略-codingwu-博客园archimedes动态规划算法-codingwu-博客园archimedes字符串匹配--暴力搜索算法-codingwu-博客园archimedes算法--枚举策略-co 查看详情

p9:数据库设计与首页接口制作(代码片段)

ReactHooks+Laravel前端博客实战阐述数据库中的表建立type表(文章类型表)article表(文章内容表)前端首页文章列表接口安装Axios模块新建`getInitialProps`方法并获取数据把数据放入到界面中阐述设计一下数据库结构,把文章的表和类... 查看详情

系统优化设计笔记--曹大公众号文章笔记

...几百万条,几千万条,几亿条,这些不同数据容量的架构设计,肯定是不一样的分布规律:好友列表:平均每个人会有多少好友,有超过100个好友的比例是多少,系统上限是多少订阅列表:双向订阅、单向订阅的关系。主数据的... 查看详情

软件工程-个人博客系统-概要设计与详细设计文档

0.   软件工程应用与实践  个人博客系统---概要设计与详细设计文档一、体系结构设计1.软件结构化设计概述该阶段主要在于定义个人博客系统的主要结构元素及其之间的关系。详细的数据流图已在需求分析文档中给出。通过... 查看详情

django入门与实践(续)

...按钮(超链接)    列表编写思路      取出数据库中所有文章对象      将文章对象们打包成列表,传递到前端      前端页面把文章以标题超链接的形式逐个列出      模板for循环     ... 查看详情

javaweb项目---博客系统

文章目录1.创建maven项目2.设计数据库3.封装数据库的操作代码3.1创建DBUtil类3.2创建类Blog(代表一篇博客)3.3创建类User(代表一个用户)3.4创建类BlogDao(对博客表进行操作)3.5创建类UserDao(对用户表进行操作)4.初始化TemplateEngine5.实现主页... 查看详情