简体   繁体   中英

How do I define a one-to-one relationship over a one-to-many relationship in a relational database?

I'm creating a database schema with the following tables (sorry for the bad pseudocode):

User
====
user_id, PK

Collection
==========
collection_id, PK
user_id, FK(User->user_id)

Issue
=====
issue_id, PK
collection_id, FK(Collection->collection_id)

There is a one-to-many relationship from User to Collection, and also from Collection to Issue. So, a single user may maintain multiple collections, each with many issues.

The problem: I would like to designate a "default" collection to be displayed when the user first logs in to the application. For the record, I'm doing this in the Django framework, but I'm more interested in the elegant platform-independent solution. When I try to make a column in User that is a Foreign Key to Collection, it complains that Collection does not exist yet (I suppose because User is created first). I could add a "default" boolean column to Collection and enforce through my application that only one record per User be "true", but that seems inelegant. I could also have a separate table, say, User_Default_Collection, which has user_id as a Foreign, Unique Key, and a collection_id column which is a Foreign Key to Collection. But I'm certain this is also less than 3rd normal form. Any suggestions?

If you want to enforce that every user must and will always have his "default" collection, then because of the obvious cycle in the inclusion dependencies you are forced into either deferred constraint checking (if your DBMS allows the FK cycle to be declared in the first place) or application-enforced integrity.

If you can tolerate users not having any default collection at all, then create a separate table DFT_COLL(userid, dft_coll_id) with key userid and FK's to both USER and COLLECTION.

If it gives you trouble in cases when a user has no default collection, maybe this can still be addressed by having the system just pick one (eg the one with the lowest [or highest] id) and implement this with a UNION view (so that if you need the default then you read the UNION view and you're guaranteed (*) to get some result).

(*) If the user has a collection at all, that is. Note that requiring a default collection and requiring that to exist, implies requiring at least one collection per user. (And the corollary of this is that if it must be allowed for a user to have no collection at all, it is nonsensical and a contradiction to require him to have a default one.)

The most plausible solution i think would be:

  1. Add nullable "default" field to Collection table
  2. Create UNIQUE constraint for used_id and default

Keep "true"-s and NULLs (no false's) in "default" column.

This will not allow for multiple Collections associated with the same user_id to have the same "default" value other than null. You don't need to develop any application logic. However, this design would not force you to always have a default collection for a user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM