Multiple column foreign key contraints

后端 未结 5 1608
你的背包
你的背包 2020-12-02 00:40

I want to setup table constraints for the following scenario and I’m not sure how to do it or if it’s even possible in SQL Server 2005.

I have three tables A,B,C. C

相关标签:
5条回答
  • 2020-12-02 00:58

    I have three tables A,B,C. C is a child of B. B will have a optional foreign key(may be null) referencing A. For performance reasons I also want table C to have the same foreign key reference to table A. The constraint on table C should be that C must reference its parent (B) and also have the same foreign key reference to A as its parent.

    You can have table B have a dual primary key (A's key, and then say an identity), and then use that to link to C. This won't allow you to have a null foreign key reference on B though, but foreign keys aren't allowed to be null anyway.

    Really if you have indexes etc. set properly, there isn't a real need to push A's key to C. Joining it to table B to get A's key won't be that much of a performance hit (like almost none).

    0 讨论(0)
  • I don't see a need to explicitly enforce the relationship from C to A. Simply follow the chain from C to B to A.

    0 讨论(0)
  • 2020-12-02 01:08

    Looks like the common ues case for you is you have A's key and you need all the matching rows in C. In which case the following query should be fast:

    select C.* 
    from B
    join C on C.Bid = B.Bid
    where C.Aid = <value>
    

    with proper indexes this should be just as fast as if you have Aid on C because they will both require an index scan followed by joining that result to the C table.

    0 讨论(0)
  • 2020-12-02 01:15

    In general I do not see a specific reason to do this -- however, you did ask.

    Thing to understand is that a relational model does not have to follow an OO model. This is a standard way to present Customer-Order-LineItem. Nothing wrong with this.

    alt text

    If I want to find all line-items belonging to a customer, I have to join via the Order table, similar to the OO dot-dot notation (Customer.Order.LineItem).

    select * 
    from Customer as c
    join Order    as o on o.CustomerId = c.CustomerId
    join LineItem as i on i.OrderId    = o.OrderId
    where CustomerID = 7 ;
    

    Suppose that I modify keys a bit, like:

    alt text

    The CustomerOrderId is an order sequence number for each customer (1,2,3 ...) and the CustomerOrderItemId is a line-item sequence number for each of the customer's orders (1,2,3 ...). Each one is easy to generate, as in

    -- next CustomerOrderId
    select coalesce(max(CustomerOrderId), 0) + 1
    from  Order
    where CustomerId = specific_customer_id;
    
    -- next CustomerOrderItemId
    select coalesce(max(CustomerOrderItemId), 0) + 1
    from  LineItem
    where CustomerId      = specific_customer_id
      and CustomerOrderId = specific_customer_order_id;
    

    Now if I want to find line-items belonging to a customer (and some customer data), I can skip the Order table.

    select * 
    from Customer as c
    join LineItem as i on i.CustomerId = c.CustomerId
    where CustomerID = 7 ;
    

    And If I do not need any specific data from the Customer table, no need to join at all. Compare this to the first example -- remember that getting line-items was the objective.

    select * 
    from LineItem
    where CustomerID = 7 ;
    

    So, with the relational model, by propagating (natural) keys, you do not have to always "stop at each station along a relationship path" in joins.

    Which is better? Depends who you ask.

    Hope you will be able to translate the underlying principle into your example -- I find it hard to work with generic (A,B,C).

    0 讨论(0)
  • 2020-12-02 01:22

    Denormalization for the purposes of improving performance is pretty common, especially if you have evidence showing its value. I assume you have good reasons for doing so, so I won't address that.

    Have you thought of simply having an insert trigger on C which sets the column referencing table A based on a lookup in table B? You may also need update triggers on C and B to ensure it is always in sync. This would ensure the column in table C which references table A is always correct, even if it isn't "enforced" by an actual constraint.

    0 讨论(0)
提交回复
热议问题