Обсуждение: Relational loops in a DB
I am designing a DB and some of the tables have a loop in their relationships. I am attaching an image of such tables.
One "course" can be offered at several dates (course offerings) and also one "course" can be thought by several "qualified trainers". A "course offering" is taught by one "qualified trainer".
I will very much appreciate your feedback. I hope my explanation is clear enough.
Respectfully,
Jorge Maldonado
Вложения
JORGE MALDONADO wrote > I am designing a DB and some of the tables have a loop in their > relationships. I am attaching an image of such tables. > > One "course" can be offered at several dates (course offerings) and also > one "course" can be thought by several "qualified trainers". A "course > offering" is taught by one "qualified trainer". > > I will very much appreciate your feedback. I hope my explanation is clear > enough. > > Respectfully, > Jorge Maldonado Note that you haven't actually asked a question here... It would have been more helpful to add cardinality indicators to the visual than try and explain it using text. Anyway, course-trainer seems to be a many-to-many relationship and so requires a separate linking table in the model. A trainer does not require a course or offering so that is an optional link which breaks any kind of circle. The course_offering FK would be against the "course-trainer" link table and not directly against course or trainer. [forgive if I get the arrow direction wrong - you'll get the idea] course <- course_trainer -> trainer course_trainer <- course_offering -> calendar You should seriously considering implementing the foreign keys using multi-column keys instead of generating a serial/surrogate on course_trainer and using that single field on course_offering. Note that in this model a course does not require any trainers but it cannot be offered until there is at least one. David J. -- View this message in context: http://postgresql.1045698.n5.nabble.com/Relational-loops-in-a-DB-tp5796019p5796021.html Sent from the PostgreSQL - novice mailing list archive at Nabble.com.
On 14/03/14 13:18, JORGE MALDONADO wrote:
I've attached my suggestion, change details to suite - if you find it useful.I am designing a DB and some of the tables have a loop in their relationships. I am attaching an image of such tables.One "course" can be offered at several dates (course offerings) and also one "course" can be thought by several "qualified trainers". A "course offering" is taught by one "qualified trainer".I will very much appreciate your feedback. I hope my explanation is clear enough.Respectfully,Jorge Maldonado
Cheers,
Gavin
Вложения
On Thu, Mar 13, 2014 at 06:18:32PM -0600, JORGE MALDONADO wrote: > I am designing a DB and some of the tables have a loop in their > relationships. I am attaching an image of such tables. Here's my shot at it: three tables: `course_catalog`, `staff` and `schedule`: sandbox=> \d course_catalog Table "public.course_catalog" Column | Type | Modifiers -------------+-----------------------+----------- course_id | character(3) | not null course_name | character varying(64) | not null Indexes: "course_catalog_pkey" PRIMARY KEY, btree (course_id) Referenced by: TABLE "schedule" CONSTRAINT "schedule_course_fkey" FOREIGN KEY (course_id) REFERENCES course_catalog(course_id) sandbox=> \d staff Table "public.staff" Column | Type | Modifiers --------------+-----------------------+----------- trainer_id | integer | not null trainer_name | character varying(64) | not null Indexes: "staff_pkey" PRIMARY KEY, btree (trainer_id) Referenced by: TABLE "schedule" CONSTRAINT "schedule_trainer_fkey" FOREIGN KEY (trainer_id) REFERENCES staff(trainer_id) sandbox=> \d schedule Table "public.schedule" Column | Type | Modifiers --------------+----------------------+----------- offering_id | character(4) | not null course_id | character(3) | not null trainer_id | integer | not null classroom_id | character varying(5) | not null start_date | date | not null Indexes: "schedule_pkey" PRIMARY KEY, btree (offering_id) "schedule_ukey" UNIQUE CONSTRAINT, btree (course_id, start_date) Foreign-key constraints: "schedule_course_fkey" FOREIGN KEY (course_id) REFERENCES course_catalog(course_id) "schedule_trainer_fkey" FOREIGN KEY (trainer_id) REFERENCES staff(trainer_id) Here's the SQL: CREATE TABLE course_catalog ( course_id character(3) NOT NULL PRIMARY KEY, course_name character varying(64) NOT NULL ); CREATE TABLE staff ( trainer_id integer NOT NULL PRIMARY KEY, trainer_name character varying(64) NOT NULL ); CREATE TABLE schedule ( offering_id character(4) NOT NULL PRIMARY KEY, course_id character(3) NOT NULL, trainer_id integer NOT NULL, classroom_id character varying(5) NOT NULL, start_date date NOT NULL, CONSTRAINT schedule_ukey UNIQUE (course_id, start_date), CONSTRAINT schedule_course_fkey FOREIGN KEY (course_id) REFERENCES course_catalog(course_id), CONSTRAINT schedule_trainer_fkey FOREIGN KEY (trainer_id) REFERENCES staff(trainer_id) ); If you want some reading material that might help you to develop this skill (besides general relational DB theory), I'll recommend "Designing Quality Databases with IDEF1X Information Models," by Thomas A Bruce. http://www.amazon.com/Designing-Quality-Databases-IDEF1X-Information/dp/0932633188 Don't let the age fool you. I found it very helpful and you can get it used for the price of postage. -- Adam Mackler
Вложения
Actually, now I see you want to keep track of qualifications to prevent an unqualified trainer from offering a course. I'll change my schema by adding a fourth table, `expertise`, and change the foreign keys of the `schedule` table to reference that instead of referencing the `course_catalog` and `staff` tables. Like so: sandbox=> \d expertise Table "public.expertise" Column | Type | Modifiers ------------+--------------+----------- trainer_id | integer | not null course_id | character(3) | not null Indexes: "expertise_pkey" PRIMARY KEY, btree (trainer_id, course_id) Foreign-key constraints: "expertise_course_fkey" FOREIGN KEY (course_id) REFERENCES course_catalog(course_id) "expertise_trainer_fkey" FOREIGN KEY (trainer_id) REFERENCES staff(trainer_id) Referenced by: TABLE "schedule" CONSTRAINT "schedule_expertise_fkey" FOREIGN KEY (trainer_id, course_id) REFERENCES expertise(trainer_id,course_id) sandbox=> \d schedule Table "public.schedule" Column | Type | Modifiers --------------+----------------------+----------- offering_id | character(4) | not null course_id | character(3) | not null trainer_id | integer | not null classroom_id | character varying(5) | not null start_date | date | not null Indexes: "schedule_pkey" PRIMARY KEY, btree (offering_id) "schedule_ukey" UNIQUE CONSTRAINT, btree (course_id, start_date) Foreign-key constraints: "schedule_expertise_fkey" FOREIGN KEY (trainer_id, course_id) REFERENCES expertise(trainer_id, course_id) -- Adam Mackler