使用匿名外键连接表

时间:2011-04-18 10:47:53

标签: sql database-design foreign-keys guid foreign-key-relationship

相关

与我的其他问题相关:

Comment system design

数据设计

假设我有一个标签表:

tblTags
-------------
TagID (int)
Name (string)

两个内容表:

tblBlogs
-------------
Anchor (GUID, Primary Key)
BlogTitle (string)
+ More custom fields

tblTutorials
-------------
Anchor (GUID, Primary Key)
TutorialTitle (string)
+ More custom fields

还会有更多带有锚点的表格,它不仅仅是2。

然后将标签与上述实体相关联:

tblTagAnchors
-------------
TagID (int, Foreign Key)
Anchor (GUID, Foreign Key)

我的问题是,一旦我建立了博客和教程与特定标签的关联,有没有办法编写查询来返回带有特定标签的博客或教程?无需对博客和教程进行单独查询?

主要用途是搜索,类似于(伪):

select from tblBlogs and tblTutorials where the GUID exists in tblTagAnchors where tagID = 5

for each record returned
    if record from Blog
        response.write("<a href=blogView.aspx?ID=" + recID)
    else if record from Tutorial
        response.write("<a href=tutorialView.aspx?ID=" + recID)
next

我正在使用SQL Server 2008 Express和ASP.net 4(c#),如果它与Linq to SQL有很大不同,但我需要的是基于设计的答案,除非是演示,否则不是任何代码。

使用多个查询是唯一的方法吗?

3 个答案:

答案 0 :(得分:5)

这将是“通常的”方法。

enter image description here

select
      p.PublicationID 
    , p.PublicationType 
    , p.PublicationTitle
    , t.TagID
    -- other blog/tutorial specific fields here
from Publication    as p
left join Blog      as b on (b.PublicationID = p.PublicationID and p.PublicationType = 'B')
left join Tutorial  as t on (t.PublicationID = p.PublicationID and p.PublicationType = 'T')
join PublicationTag as x on x.PublicationID = p.PublicationID
join Tag            as t on t.TagID = x.TagID ;

您可以将其打包到视图中,以帮助隔离应用程序代码中的任何未来架构更改。

答案 1 :(得分:3)

我建议使用联盟。这个查询只有一个结果集,但它在一起合并查询。

Select b.rec_id,'Blog' as type from tblBlogs b
inner join tblTagAnchors ta on ta.anchor = b.anchor
where ta.tagid = 5
union
Select t.rec_id,'Tutorials' as type from tblTutorials t
inner join tblTagAnchors ta on ta.anchor = t.anchor
where ta.tagid = 5

然后在你的vb代码中,只需在类型字段上执行if。在linq中,您必须使用.union命令编写查询。我刚写了一个通用的sql解决方案。它可以很容易地转换为linq。

作为旁注,有条件的外键让我想要快门。在现代数据库设计中,您应该始终避免使用可以转到多个表的密钥,这很难强制执行CRUD,并且更难以查询。我建议创建一个超级类型的tblBlogs和tblTutorials,如tblWebsites,并使密钥转到超类型。

答案 2 :(得分:1)

您不仅可以使用一个查询选择必要的数据,还可以摆脱客户端中的if条件,即决定输出href的条件,因为您可以选择数据并在同一查询中同时构造输出字符串。然后,您的客户端只需迭代结果集并输出字符串。

基本上,你查询将是两个子查询的UNION,但我会做的与@JStead提供的方式有所不同,这可能是这样的:

SELECT
  OutputString = '<a href=' + SrcName + 'View.aspx?ID=' + CAST(x.recID AS varchar)
FROM (
  SELECT 'blog' AS SrcName, Anchor, recID
  FROM tblBlogs
  UNION ALL
  SELECT 'tutorial' AS SrcName, Anchor, recID
  FROM tblTutorials
) x
  INNER JOIN tblTagAnchors ta ON x.Anchor = ta.Anchor

如您所见,查询返回准备输出的数据。因此,客户端的逻辑简化为:

for each record returned
    response.write(OutputString)
next