如何用publish/drafttable设计sql数据库?

How to design a sql database with a publish/draft table?

我想知道如何做博客数据库的方案。作者撰写文章并将其发布在博客上。这对于像

这样的 table 来说非常简单

Author, Article, Blog

不过文章也可以有草稿。读者看不到草稿,文章发表后博客的读者可以看到。已发表的文章可以取消发表,成为草稿。

如何连接

draft

publish

tables 与文章和博客 tables?有必要吗?或者只是在文章 table 中添加一些专栏?比如 IsPublished 之类的?

有几种方法可以解决这个问题。一种是在你的内容上有一个 status 标志,这对简单的网站很有用。另一个是连接 table 将内容连接到应该显示的位置、方式和时间。

对于简单的网站,您只需在内容 table 中添加一个 status 标志。

create type statuses as enum ('published', 'draft');

create table posts (
    id serial,
    author integer references people(id),
    content text not null,
    ...whatever other data...
    status statuses default 'draft'
);

我用了一个PostgreSQL enumerated type来减少存储空间space(不是很重要),所以拼写错误会被发现(重要),所以有一个地方可以看到所有可能的状态是而不是随意添加它们(也很重要)。

然后您可以 select 所有已发布的 post。

select *
from posts
where author = ? and
      status = 'published'

这很简单,但是显示和内容是一起使用的。如果您忘记检查 status 标志,您将显示草稿 posts.


status 标志的一个变体是有一个 "publish at" 日期。在此之前它不会被显示。过了这个时间就可以了。

create table posts (
    id serial,
    author integer references people(id),
    content text not null,
    ...whatever other data...
    publish_at datetime default '9999-12-31'
);

然后你可以通过查看 publish_at 是否小于当前日期时间来检查它是否应该显示。

select *
from posts
where author = ? and
      publish_at < current_timestamp

默认为“9999-12-31”,所有 post 都默认取消发布。这将 published/draft 与自动发布 post 的能力相结合,而无需 运行 任何额外代码。


一个更强大的解决方案是加入 table 来确定要发布的内容和位置。从相同的 posts table 开始,但没有 status 列。

create table posts (
    id serial,
    author integer references people(id),
    content text not null,
    ...whatever other data...
);

比起一个人的博客。

create table blogs (
    id serial,
    curator integer references people(id)
);

然后创建连接 table 将 post 与博客 [​​=64=] 连接起来。

create table blog_posts (
    blog integer references blogs(id),
    post integer references posts(id),
    posted datetime not null default current_timestamp
);

现在,当某些东西是 "published" 时,它被插入到 blog_posts 中。没有状态标志。如果您想查看用户的博客 posts...

select *
from blog_posts
join blogs on blogs.id = blog_posts.blog
where blogs.curator = ?
order by posted desc;

这里的优点是通过向 blog_posts table 添加更多连接 table 或更多字段,一个 post 可以出现在多个位置。并且没有 status 字段要记住包含在每个语句中。它要么在连接 table 中,要么不在。

blog_posts 也可以具有 publish_at 字段。

用这个可视化它:

在 "authors" table:

basically all the information about the authors

在 "articles" table:

each article will have one author (generally... hmmmm but it can have more than one possibly but this will do). so the foreign key authors_id.

对于已发布和草稿:

"published" and "draft" are in the status field. In this case is enum('published', 'draft'). On your isPublished? I don't have anything against db designs with boolean values (ie yes/no, true/false) but it would be clearer if you have it as an enum. Probably later on you'll be adding there another status and your isPublished is not relevant anymore. A case could be: you'll need a status later on that says: "scheduled publish" or say "scheduled unpublish" or any other status.

关于 "blog" table:

You don't necessarily need that if you have only one blog. But if you have several blogs, then you'd need that table.

至于上面的sql:

CREATE TABLE IF NOT EXISTS `authors` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(200) NULL,
  `status` ENUM('active', 'inactive') NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB

CREATE TABLE IF NOT EXISTS `articles` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(60) NULL,
  `content` TEXT NULL,
  `status` ENUM('published', 'draft') NULL,
  `datetime` INT NULL,
  `authors_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_articles_authors_idx` (`authors_id` ASC),
  CONSTRAINT `fk_articles_authors`
    FOREIGN KEY (`authors_id`)
    REFERENCES `authors` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
 ENGINE = InnoDB