代码之家  ›  专栏  ›  技术社区  ›  Dillie-O

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

  •  2
  • Dillie-O  · 技术社区  · 17 年前

    我的数据库中有两个简单的表。包含卡的Id、名称和文本的“卡”表,以及包含卡的Id和详细说明卡的规则的文本的“规则”表。

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

    最好的方法是什么?我的环境是SQL2005,但是任何一种“DB不可知”的解决方案在这里都被广泛接受。

    2 回复  |  直到 17 年前
        1
  •  4
  •   Tom H zenazn    17 年前

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

    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
    

    您的前端将负责维护引用。这可能是可取的,因为它避免了有人在规则文本中忘记在卡片名称周围加引号等问题。

        2
  •  1
  •   George Mastros    17 年前

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

    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) + '"%'
    

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