如何为我的数据创建交叉引用表/查询?

时间:2008-11-26 15:37:38

标签: sql database-design cross-reference

我的数据库中有两个简单的表。一张“卡片”表,其中包含卡片的身份证,姓名和文字,以及包含卡片身份证明的“裁定”表格,以及详细说明该卡片裁决的文字。

在裁决文本中,通常会提到数据库中的另一张卡片。在文本中很容易找到它,因为每张卡都封装在文本中的引号内。在裁决文本中引用多张牌并不罕见。

我想做的是能够创建一个交叉引用表(或者如果它足够有效的程序),这样当我提交卡的查询时,我可以找到直接引用的所有统治记录通过Id获取卡片,并获取文本中引用卡片名称的所有裁定记录。

最好的方法是什么?我的环境是SQL 2005,但是这里有很多“数据库不可知”的解决方案。

2 个答案:

答案 0 :(得分:4)

这似乎是一个相当简单和常见的关系问题,由交叉引用表解决。例如:

CREATE TABLE dbo.Cards (
    id        INT            NOT NULL,
    name      VARCHAR(50)    NOT NULL,
    card_text VARCHAR(4000)  NOT NULL,
    CONSTRAINT PK_Cards PRIMARY KEY CLUSTERED (id)
)
GO
CREATE TABLE dbo.Card_Rulings (
    card_id        INT            NOT NULL,
    ruling_number  INT            NOT NULL,
    ruling_text    VARCHAR(4000)  NOT NULL,
    CONSTRAINT PK_Card_Rulings PRIMARY KEY CLUSTERED (card_id, ruling_number)
)
GO
CREATE TABLE dbo.Card_Ruling_Referenced_Cards (
    parent_card_id    INT    NOT NULL,
    ruling_number     INT    NOT NULL,
    child_card_id     INT    NOT NULL,
    CONSTRAINT PK_Card_Ruling_Referenced_Cards PRIMARY KEY CLUSTERED (parent_card_id, ruling_number, child_card_id)
)
GO
ALTER TABLE dbo.Card_Rulings
ADD CONSTRAINT FK_CardRulings_Cards FOREIGN KEY (card_id) REFERENCES dbo.Cards(id)
GO
ALTER TABLE dbo.Card_Ruling_Referenced_Cards
ADD CONSTRAINT FK_CardRulingReferencedCards_CardRulings FOREIGN KEY (parent_card_id, ruling_number) REFERENCES dbo.Card_Rulings (card_id, ruling_number)
GO
ALTER TABLE dbo.Card_Ruling_Referenced_Cards
ADD CONSTRAINT FK_CardRulingReferencedCards_Cards FOREIGN KEY (child_card_id) REFERENCES dbo.Cards(id)
GO

获取卡片的所有卡片裁决:

SELECT *
FROM dbo.Cards C
INNER JOIN dbo.Card_Rulings CR ON CR.card_id = C.id
WHERE C.id = @card_id

要获得给定卡片裁决中引用的所有卡片:

SELECT C.*
FROM dbo.Card_Rulings CR
INNER JOIN dbo.Card_Ruling_Referenced_Cards CRRC ON CRRC.parent_card_id = CR.card_id
INNER JOIN dbo.Cards C ON C.id = CRRC.child_card_id
WHERE CR.card_id = @card_id

这完全不是我的头脑而且未经过测试,因此可能存在语法错误等。

您的前端将负责维护参考。这可能是可取的,因为它避免了某人忘记在裁决文本等中放置卡片名称的问题。

答案 1 :(得分:1)

我建议您创建另一个存储引用的表。然后,创建一个用于维护此表的插入和更新触发器。这样,您将有一个更快的查询来返回您要查找的数据。

我认识到最初填充此表可能有点困难,这就是我在下面展示一些示例数据(和查询)的原因,您可以用它来帮助您入门。

Declare @Card Table(Id Int, Name VarChar(20), CardText VarChar(8000))

Declare @Ruling Table(CardId Int, CardRuling VarChar(8000))

Insert Into @Card Values(1, 'Card 1', 'This is the card ID = 1')
Insert Into @Card Values(2, 'Card 2', 'This is the card id = 2.')
Insert Into @Card Values(3, 'Card 3', 'This is the card id = 3.')

Insert Into @Ruling Values(1, 'This is the ruling for 1 which references "2"')
Insert Into @Ruling Values(2, 'This is the ruling for 2 which references nothing')
Insert Into @Ruling Values(3, 'This is the ruling for 3 which references "1" and "2"')

Declare @CardId Int
Set @CardId = 1

Select  * 
From    @Card As Card
        Inner Join @Ruling As Ruling
            On Card.Id = Ruling.CardId
        Left Join @Card As CardReferences
            On Ruling.CardRuling Like '%"' + Convert(VarChar(10), CardReferences.Id) + '"%'

编辑:

我建议使用另一个表的原因是因为您可能会对此查询的性能感到失望,尤其是对于大型表。