【问题标题】:is there a way to enforce a set of values for a column of a database table?有没有办法为数据库表的列强制执行一组值?
【发布时间】:2011-04-14 18:34:30
【问题描述】:

我有一个表,在其中一个列中我将指定实体的类型。实体只能是三种类型 - 标题、图像或评论,因此我想确保表列应该只接受这三个字符串之一。有没有办法将此约束放入 ms sql server 2008 中?

编辑:- 添加了 db 图以获取改进设计的提示。

设计:- 1)一个故事板有许多幻灯片,每张幻灯片可以有一个或多个标题或图像。

2)每个故事板可以有一个或多个作者,以及零个或多个审阅者。

3) 每个对象图像、幻灯片和标题(可能稍后会出现更多对象,如音频等)可以在它们上面有 cmets。这些 cmets 可以由作者或审稿人给出。 为了存储 cmets,我创建了一个评论表。

4)有必要记住幻灯片的顺序和幻灯片中的图像顺序,为此我使用幻灯片和图像编号字段。

5) 由于可以在任何对象上给出注释,我需要为每个对象设置一个全局 ID,因为它们的引用将存储在注释表中。为了维护全局 ID,所有以名称结尾的字段GID 是使用默认值生成的唯一标识符:NEWID()。

请为此数据库设计提出改进建议。

【问题讨论】:

  • 嘿deovrat,您应该选择一个已接受的答案并将其作为新问题发布。在发布答案后更改问题会给未来的访问者带来混乱的体验。只是一个建议。
  • 感谢您的建议 :),我在这里发布了一个新问题 stackoverflow.com/questions/5660583/…

标签: sql sql-server database-design


【解决方案1】:

这是使用检查约束的方法:

create table #tableWithConstrainedColumn (
    constrainThis varchar(20)
)

ALTER TABLE #tableWithConstrainedColumn ADD CONSTRAINT TempCheck
    CHECK (constrainThis in ('caption', 'image', 'comment'))

-- this statement will succeed
insert into #tableWithConstrainedColumn
select 'caption'
-- this statement will fail
insert into #tableWithConstrainedColumn
select 'captions'

drop table #tableWithConstrainedColumn

您也可以定义数据类型,但我不建议这样做:http://msdn.microsoft.com/en-us/library/aa933121(v=sql.80).aspx

正如@Widor 刚刚建议的那样,外键是最好的方法。

【讨论】:

  • 这可以缩短为CHECK (constrainThis IN ('caption', 'image','comment'))
  • 我倾向于创建一个“实体”表(正如@deovrat 所说的那样),其中“标题”、“图像”和“评论”作为具有自己 ID 的记录。然后,不要将实体名称插入主表,而是创建一个 FK,以确保 EntityID 是 Entity 表中定义的名称之一。这样,没有人可以删除主表中的一种实体和孤立记录。
  • 我已经添加了数据库的图表和描述。请提出您能想到的设计改进。谢谢
【解决方案2】:

听起来像是Foreign Keys 的工作?

【讨论】:

  • +1 这绝对是正确的设计,但检查约束可能更轻量级。
  • @Milimetric - 有些人会质疑 FK 是“正确”的方式。只是想找到一篇关于这个问题的博文......编辑:找到它weblogs.sqlteam.com/davidm/archive/2004/02/17/882.aspx
  • 查看我对@Milimetric 回答的推理。 @Martin:我看到了该博客中的观点,但我会说第一条评论中的这句话是为什么我感觉不对 - “不仅如此,而且如果这些值在 CHECK 约束中,您无法枚举“允许”值是什么”
  • @Widor - 只是指出有些人会认为检查约束是“正确”的方式。 TBH 我发现我链接的博客文章非常激进和居高临下,并且通常会自己使用 FK。
  • hm...我绝对认为 fk 是正确的方法,但检查约束,如非规范化表,可能有它们的位置。提到那篇文章,我认为关键是“当我们想要添加更多值时会发生什么?”
【解决方案3】:

啊哈,在那种情况下问题的性质是不同的!因此,我在这里的第二个答案。

我承认我不能 100% 确定“最佳”解决方案是什么。我认为您计划如何查询这些数据将在一定程度上决定您存储它的方式。

根据您发布的额外信息,我建议剥离 Comment 表,以便它存储有关 cmets 的信息。丢失ObjID, ObjType 字段,可能还有usertype - 那不应该在User 表中吗?

然后,我建议将三个新表添加到您的架构中:SlideCommentCaptionCommentImageComment,每个表只有两个字段:
一个用于存储CommentId(它将具有Comment 表的 FK),另一个用于存储适当的 Slide-、Caption- 或 Image- GID。

因此,这些新表仅用于将 Comment 连接到创建它们的实体。这应该使您能够以您想要的方式查询数据,而不必担心它指的是哪个“实体”。

【讨论】:

    【解决方案4】:

    使用检查约束或触发 BEFORE INSERT、UPDATE 并将此验证编码到其中。

    【讨论】:

    • 否!一个简单的检查约束可以更有效地做到这一点,然后优化器可以使用这些信息。
    • 是的,对不起,这个是-1。触发器可能会起作用,但它们应该是最后的手段。如果不谨慎使用,它们将成为维护和测试的噩梦。
    猜你喜欢
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    相关资源
    最近更新 更多