in reply to Normalisation Question (OT but trust me, perl implementation)

gmax has written Database normalization the easier way (which resulted in DBSchema::Normalizer).

Aside from that, you gotta clarify which Normal Form you're going for. Here's how I see it (aiming for 2NF -- sure Movies aren't Episodes, but the intent is clear enough):

my $tables = q~ #A Person is independent of everything else. CREATE TABLE Person ( Id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, Name VARCHAR(255), KEY( Name ), PRIMARY KEY( Id ) ); #An Actor is a Person. #(An Actor plays Roles). CREATE TABLE Actor ( Id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, PersonId INT(11) UNSIGNED NOT NULL REFERENCES Person(Id), KEY( PersonId ), PRIMARY KEY( Id ) ); #A Director is a Person. #A Director directs Movies. #(A Director can also be an Actor). CREATE TABLE Director ( Id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, PersonId INT(11) UNSIGNED NOT NULL REFERENCES Person(Id), MovieId INT(11) UNSIGNED NOT NULL REFERENCES Movie(Id), KEY( MovieId ), KEY( PersonId ), PRIMARY KEY( Id ) ); #Roles are played by Actors. #Roles occur in Movies. #A Role is a Person. CREATE TABLE Role ( Id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, ActorId INT(11) UNSIGNED NOT NULL REFERENCES Actor(Id), MovieId INT(11) UNSIGNED NOT NULL REFERENCES Movie(Id), PersonId INT(11) UNSIGNED NOT NULL REFERENCES Person(Id), KEY( PersonId ), KEY( ActorId ), KEY( MovieId ), PRIMARY KEY( Id ) ); #A movie has a Title. #(A movie may have: Roles, Directors, Actors, Writers). CREATE TABLE Movie ( Id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, Title VARCHAR(255), PRIMARY KEY( Id ) ); ~; use strict; use warnings; use SQL::Translator; my %To = ( POD => 'pod', XML => 'xml', HTML => 'html', Raw => 'Raw', GraphViz => 'png', ClassDBI => 'pm', MySQL => 'sql', SQLite => 'sql', Oracle => 'sql', PostgreSQL => 'sql', Sybase => 'sql', ); for my $to ( sort keys %To ){ print STDERR "Translating to $to ...\n"; my $translator = SQL::Translator->new( debug => 0, # PrINT debug info trace => 0, # PrINT Parse::RecDescent trace no_comments => 1, # Don't include comments in output show_warnings => 1, # PrINT name mutations, conflicts add_drop_table => 1, # Add "drop table" statements data => \$tables, producer_args => { layout => 'dot', node_shape => 'trapezium', #plaintext diamond house }, ); my $output = $translator->translate( from => "MySQL", to => $to, ) or warn "\n\nFATAL ERROR: ", $translator->error and next; my $file = __FILE__ ."_$to.$To{$to}"; open my $fh, '>', $file or warn "Can't clobber $file : $!" && +next; binmode $fh; print {$fh} $output; close $fh; } __END__

Description of Schema

Person

Top
Field Name Data Type Size Default Other Foreign Key
Id INT 11 PRIMARY KEY, NOT NULL
Name VARCHAR 255

Indices

Name Fields
Name

Actor

Top
Field Name Data Type Size Default Other Foreign Key
Id INT 11 PRIMARY KEY, NOT NULL
PersonId INT 11 NOT NULL Person.Id

Indices

Name Fields
PersonId

Director

Top
Field Name Data Type Size Default Other Foreign Key
Id INT 11 PRIMARY KEY, NOT NULL
PersonId INT 11 NOT NULL Person.Id
MovieId INT 11 NOT NULL Movie.Id

Indices

Name Fields
MovieId
PersonId

Role

Top
Field Name Data Type Size Default Other Foreign Key
Id INT 11 PRIMARY KEY, NOT NULL
ActorId INT 11 NOT NULL Actor.Id
MovieId INT 11 NOT NULL Movie.Id
PersonId INT 11 NOT NULL Person.Id

Indices

Name Fields
PersonId
ActorId
MovieId

Movie

Top
Field Name Data Type Size Default Other Foreign Key
Id INT 11 PRIMARY KEY, NOT NULL
Title VARCHAR 255

Created by SQL::Translator

MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
** The third rule of perl club is a statement of fact: pod is sexy.

Replies are listed 'Best First'.
Re: Re: Normalisation Question (OT but trust me, perl implementation)
by dws (Chancellor) on Aug 04, 2003 at 08:46 UTC
    That works, but since in this scheme Actor is a subset of Person, you don't need two tables.

    Clarification: That a Person is an Actor is implied by the fact of their portraying a Character (a Role). Hence, you can collapse Actor into Person, and use a single table.

Re: Re: Normalisation Question (OT but trust me, perl implementation)
by eric256 (Parson) on Aug 04, 2003 at 17:13 UTC

    A Role should not need both an ActorID and a person ID, since an ActorID is keyed by a single personID, and Actor and Person share a 1-to-1 relation. Very nice presentation though.

    ___________
    Eric Hodges