From: shapper on
On Jul 8, 10:08 pm, Erland Sommarskog <esq...(a)sommarskog.se> wrote:
> shapper (mdmo...(a)gmail.com) writes:
> > Every user should have a profile.
> > The reason why I have the USERS table and the PROFILE table is the
> > following:
>
> > From project to project the USERS table contains everything needed for
> > my authentication system and it is always the same.
> > The profile table contains that info for the USER that can be
> > different from project to project.
> > For example, in project X I might need fields A, B and C and in
> > project Y I might need fields A, B, .... O, P.
>
> > So what I need to change is the Profile table.
> > The USERS table, its mappings, repositories, etc is always the same.
> > I don't need to change it.
>
> > Does this make sense?
>
> I can see the practical reasoning behind it, but from a strict data-
> modelling perspective it is not really kosher. Not a major violation,
> but since there are no commit-time constraints in SQL Server, you
> cannot set up any constraint to ensure that all rows in Users have a
> matching row in Profiles.

Wouldn't that be possible by using:

create table dbo.Profiles
(
UserId int not null,
Birthday datetime not null,
City nvarchar(100) null,
DistrictId int not null,
GenderId int not null,
[Name] nvarchar(100) not null,
Newsletter bit not null constraint DF_Users_Newsletter default(0),
Phone nvarchar(20) null
)

I removed the PK. Then Profile is just a "break" of table user ...
Does this make sense? It is like "breaking" one table in two or not?

In fact I think in ASP.NET Membership SQL tables they do something
like this ...~

I can always have all fields (used in authentication system and the
ones that are common to all users like City, Birthday, etc) in Users
table. Basically get rid of Profile table:

-- Users
create table dbo.Users
(
Id int identity not null,
Approved bit not null constraint DF_Users_Approved default(0),
Comment nvarchar(2000) null,
Created datetime not null,
Email nvarchar(200) not null,
LastLock datetime not null,
LastLogin datetime not null,
LastPasswordChange datetime not null,
LastReset datetime not null,
Locked bit not null constraint DF_Users_Locked default(0),
[Password] varbinary(200) not null,
PasswordAttemptCount int not null,
PasswordAttemptStart datetime not null,
Salt varbinary(800) not null,
Updated datetime not null,
Username nvarchar(40) not null constraint U_Users_Username unique,
Birthday datetime not null,
City nvarchar(100) null,
DistrictId int not null,
GenderId int not null,
[Name] nvarchar(100) not null,
Newsletter bit not null constraint DF_Users_Newsletter default(0),
Phone nvarchar(20) null,
constraint PK_Users primary key clustered(Id)
) -- Users

-- UsersRoles
create table dbo.UsersRoles
(
UserId int not null,
RoleId int not null,
constraint PK_UsersRoles primary key clustered(UserId, RoleId)
) -- UsersRoles

-- Professors
create table dbo.Professors
(
Id int identity not null,
UserId int not null,
CurriculumVitae nvarchar(max) null,
Mobile nvarchar(20) null,
Phone nvarchar(20) null
constraint PK_Professors primary key clustered(Id)
)

But I think here there would be a problem to.

For a user I can have no record professors or one record in
professors ... no more then one ...

What approach would you use?

Thanks,
Miguel

From: Erland Sommarskog on
shapper (mdmoura(a)gmail.com) writes:
>> I can see the practical reasoning behind it, but from a strict data-
>> modelling perspective it is not really kosher. Not a major violation,
>> but since there are no commit-time constraints in SQL Server, you
>> cannot set up any constraint to ensure that all rows in Users have a
>> matching row in Profiles.
>
> Wouldn't that be possible by using:
>
> create table dbo.Profiles
> (
> UserId int not null,
> Birthday datetime not null,
> City nvarchar(100) null,
> DistrictId int not null,
> GenderId int not null,
> [Name] nvarchar(100) not null,
> Newsletter bit not null constraint DF_Users_Newsletter default(0),
> Phone nvarchar(20) null
> )
>
> I removed the PK. Then Profile is just a "break" of table user ...
> Does this make sense? It is like "breaking" one table in two or not?

That makes even less sense. Now there can be multiple profiles for
the same user. If you are to have two tables, you need the PK *and*
you need an FK to Users, so you don't get profiles without users-

> I can always have all fields (used in authentication system and the
> ones that are common to all users like City, Birthday, etc) in Users
> table. Basically get rid of Profile table:

That would be the right thing do to from a pure data-modelling perspective.
Thereby not saying that you desire to have a table which is static from
project to project should be ignored. Having two tables may indeed be
the best practical solution.

> create table dbo.Professors
> (
> Id int identity not null,
> UserId int not null,
> CurriculumVitae nvarchar(max) null,
> Mobile nvarchar(20) null,
> Phone nvarchar(20) null
> constraint PK_Professors primary key clustered(Id)
> )
>
> But I think here there would be a problem to.
>
> For a user I can have no record professors or one record in
> professors ... no more then one ...

The PK in Profressors should be UserId. And an FK to Users. Here it
is OK to use a separte table, since this only apply to a subset of
the users. You could have all columns in Users, and a ton of constraints
say that this column is mandatory for professors and must be NULL
for everyone else, but that gets messy.


--
Erland Sommarskog, SQL Server MVP, esquel(a)sommarskog.se

Links for SQL Server Books Online:
SQL 2008: http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
SQL 2005: http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
SQL 2000: http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

From: shapper on
On Jul 9, 10:19 am, Erland Sommarskog <esq...(a)sommarskog.se> wrote:
> shapper (mdmo...(a)gmail.com) writes:
> >> I can see the practical reasoning behind it, but from a strict data-
> >> modelling perspective it is not really kosher. Not a major violation,
> >> but since there are no commit-time constraints in SQL Server, you
> >> cannot set up any constraint to ensure that all rows in Users have a
> >> matching row in Profiles.
>
> > Wouldn't that be possible by using:
>
> > create table dbo.Profiles
> > (
> >   UserId int not null,
> >   Birthday datetime not null,
> >   City nvarchar(100) null,
> >   DistrictId int not null,
> >   GenderId int not null,
> >   [Name] nvarchar(100) not null,
> >   Newsletter bit not null constraint DF_Users_Newsletter default(0),
> >   Phone nvarchar(20) null
> > )
>
> > I removed the PK. Then Profile is just a "break" of table user ...
> > Does this make sense? It is like "breaking" one table in two or not?
>
> That makes even less sense. Now there can be multiple profiles for
> the same user. If you are to have two tables, you need the PK *and*
> you need an FK to Users, so you don't get profiles without users-
>
> > I can always have all fields (used in authentication system and the
> > ones that are common to all users like City, Birthday, etc) in Users
> > table. Basically get rid of Profile table:
>
> That would be the right thing do to from a pure data-modelling perspective.
> Thereby not saying that you desire to have a table which is static from
> project to project should be ignored. Having two tables may indeed be
> the best practical solution.
>
> > create table dbo.Professors
> > (
> >   Id int identity not null,
> >   UserId int not null,
> >   CurriculumVitae nvarchar(max) null,
> >   Mobile nvarchar(20) null,
> >   Phone nvarchar(20) null
> >     constraint PK_Professors primary key clustered(Id)
> > )
>
> > But I think here there would be a problem to.
>
> > For a user I can have no record professors or one record in
> > professors ... no more then one ...
>
> The PK in Profressors should be UserId. And an FK to Users. Here it
> is OK to use a separte table, since this only apply to a subset of
> the users. You could have all columns in Users, and a ton of constraints
> say that this column is mandatory for professors and must be NULL
> for everyone else, but that gets messy.
>
> --
> Erland Sommarskog, SQL Server MVP, esq...(a)sommarskog.se
>
> Links for SQL Server Books Online:
> SQL 2008:http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
> SQL 2005:http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
> SQL 2000:http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

Hello,

I recreated my code for the database following what seems logic to me:

1 - A USER can have many ROLES
2 - A USER can have one PROFILE.
3 - A USER can be a PROFESSOR or not.
4 - A USER PROFILE can have only one DISTRICT.
5 - A USER PROFILE can have only one GENDER.
6 - A USER PROFESSOR can have many LEVELS.
7 - A USER PROFESSOR can have many SUBJECTS.

Then I created an Entity Framework 4 model from it.
My DDL seems logic and my EF4 model seems to be according to it.
I placed all constraints next to each table to be easier to see.

-- Districts
create table dbo.Districts
(
Id int identity not null,
[Name] nvarchar(100) not null,
constraint Districts_PK primary key clustered(Id)
) -- Districts

-- Genders
create table dbo.Genders
(
Id int identity not null,
[Name] nvarchar(20) not null,
constraint Genders_PK primary key clustered(Id)
) -- Genders

-- Levels
create table dbo.Levels
(
Id int identity not null,
[Name] nvarchar(20) not null,
constraint Levels_PK primary key clustered(Id)
) -- Levels

-- Roles
create table dbo.Roles
(
Id int identity not null,
[Name] nvarchar(40) not null,
constraint Roles_PK primary key clustered(Id)
) -- Roles

-- Subjects
create table dbo.Subjects
(
Id int not null,
[Name] nvarchar(100) null,
constraint Subjects_PK primary key clustered(Id)
) -- Subjects

-- Users
create table dbo.Users
(
Id int identity not null,
Approved bit not null constraint Users_Approved_DF default(0),
Comment nvarchar(2000) null,
Created datetime not null,
Email nvarchar(200) not null,
LastLock datetime not null,
LastLogin datetime not null,
LastPasswordChange datetime not null,
LastReset datetime not null,
Locked bit not null constraint Users_Locked_DF default(0),
[Password] varbinary(200) not null,
PasswordAttemptCount int not null,
PasswordAttemptStart datetime not null,
Salt varbinary(800) not null,
Updated datetime not null,
Username nvarchar(40) not null constraint Users_Username_U unique,
constraint Users_U primary key clustered(Id)
) -- Users

-- Profiles
create table dbo.Profiles
(
Id int not null,
Birthday datetime not null,
City nvarchar(100) null,
DistrictId int not null,
GenderId int not null,
[Name] nvarchar(100) not null,
Newsletter bit not null constraint Users_Newsletter_DF default(0)
constraint Profiles_PK primary key clustered(Id),
constraint Profiles_Users_FK foreign key(Id) references dbo.Users(Id)
on delete cascade on update cascade,
constraint Profiles_Districts_FK foreign key(DistrictId) references
dbo.Districts(Id) on delete cascade on update cascade,
constraint Profiles_Genders_FK foreign key(GenderId) references
dbo.Genders(Id) on delete cascade on update cascade
)

-- Professors
create table dbo.Professors
(
Id int not null,
CurriculumVitae nvarchar(max) null,
Mobile nvarchar(20) null,
Phone nvarchar(20) null
constraint Professors_PK primary key clustered(Id),
constraint Professors_Users_FK foreign key(Id) references
dbo.Users(Id) on delete cascade on update cascade
)

-- ProfessorsLevels
create table dbo.ProfessorsLevels
(
ProfessorId int not null,
LevelId int not null,
constraint ProfessorsLevels_PK primary key clustered(ProfessorId,
LevelId),
constraint ProfessorsLevels_Professors_FK foreign key(ProfessorId)
references dbo.Professors(Id) on delete cascade on update cascade,
constraint ProfessorsLevels_Levels_FK foreign key(LevelId) references
dbo.Levels(Id) on delete cascade on update cascade
) -- ProfessorsLevels

-- ProfessorsSubjects
create table dbo.ProfessorsSubjects
(
ProfessorId int not null,
SubjectId int not null,
constraint ProfessorsSubjects_PK primary key
clustered(ProfessorId, SubjectId),
constraint ProfessorsSubjects_Professors_FK foreign key(ProfessorId)
references dbo.Professors(Id) on delete cascade on update cascade,
constraint ProfessorsSubjects_Subjects_FK foreign key(SubjectId)
references dbo.Subjects(Id) on delete cascade on update cascade
) -- ProfessorsSubjects

-- UsersRoles
create table dbo.UsersRoles
(
UserId int not null,
RoleId int not null,
constraint UsersRoles_PK primary key clustered(UserId, RoleId),
constraint UsersRoles_Users_FK foreign key(UserId) references
dbo.Users(Id) on delete cascade on update cascade,
constraint UsersRoles_Roles_FK foreign key(RoleId) references
dbo.Roles(Id) on delete cascade on update cascade
) -- UsersRoles

What do you think?

Thank You,
Miguel

From: shapper on
On Jul 9, 12:25 pm, shapper <mdmo...(a)gmail.com> wrote:
> On Jul 9, 10:19 am, Erland Sommarskog <esq...(a)sommarskog.se> wrote:
>
>
>
>
>
> > shapper (mdmo...(a)gmail.com) writes:
> > >> I can see the practical reasoning behind it, but from a strict data-
> > >> modelling perspective it is not really kosher. Not a major violation,
> > >> but since there are no commit-time constraints in SQL Server, you
> > >> cannot set up any constraint to ensure that all rows in Users have a
> > >> matching row in Profiles.
>
> > > Wouldn't that be possible by using:
>
> > > create table dbo.Profiles
> > > (
> > >   UserId int not null,
> > >   Birthday datetime not null,
> > >   City nvarchar(100) null,
> > >   DistrictId int not null,
> > >   GenderId int not null,
> > >   [Name] nvarchar(100) not null,
> > >   Newsletter bit not null constraint DF_Users_Newsletter default(0),
> > >   Phone nvarchar(20) null
> > > )
>
> > > I removed the PK. Then Profile is just a "break" of table user ...
> > > Does this make sense? It is like "breaking" one table in two or not?
>
> > That makes even less sense. Now there can be multiple profiles for
> > the same user. If you are to have two tables, you need the PK *and*
> > you need an FK to Users, so you don't get profiles without users-
>
> > > I can always have all fields (used in authentication system and the
> > > ones that are common to all users like City, Birthday, etc) in Users
> > > table. Basically get rid of Profile table:
>
> > That would be the right thing do to from a pure data-modelling perspective.
> > Thereby not saying that you desire to have a table which is static from
> > project to project should be ignored. Having two tables may indeed be
> > the best practical solution.
>
> > > create table dbo.Professors
> > > (
> > >   Id int identity not null,
> > >   UserId int not null,
> > >   CurriculumVitae nvarchar(max) null,
> > >   Mobile nvarchar(20) null,
> > >   Phone nvarchar(20) null
> > >     constraint PK_Professors primary key clustered(Id)
> > > )
>
> > > But I think here there would be a problem to.
>
> > > For a user I can have no record professors or one record in
> > > professors ... no more then one ...
>
> > The PK in Profressors should be UserId. And an FK to Users. Here it
> > is OK to use a separte table, since this only apply to a subset of
> > the users. You could have all columns in Users, and a ton of constraints
> > say that this column is mandatory for professors and must be NULL
> > for everyone else, but that gets messy.
>
> > --
> > Erland Sommarskog, SQL Server MVP, esq...(a)sommarskog.se
>
> > Links for SQL Server Books Online:
> > SQL 2008:http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
> > SQL 2005:http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
> > SQL 2000:http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx
>
> Hello,
>
> I recreated my code for the database following what seems logic to me:
>
> 1 - A USER can have many ROLES
> 2 - A USER can have one PROFILE.
> 3 - A USER can be a PROFESSOR or not.
> 4 - A USER PROFILE can have only one DISTRICT.
> 5 - A USER PROFILE can have only one GENDER.
> 6 - A USER PROFESSOR can have many LEVELS.
> 7 - A USER PROFESSOR can have many SUBJECTS.
>
> Then I created an Entity Framework 4 model from it.
> My DDL seems logic and my EF4 model seems to be according to it.
> I placed all constraints next to each table to be easier to see.
>
> -- Districts
> create table dbo.Districts
> (
>   Id int identity not null,
>   [Name] nvarchar(100) not null,
>     constraint Districts_PK primary key clustered(Id)
> ) -- Districts
>
> -- Genders
> create table dbo.Genders
> (
>   Id int identity not null,
>   [Name] nvarchar(20) not null,
>     constraint Genders_PK primary key clustered(Id)
> ) -- Genders
>
> -- Levels
> create table dbo.Levels
> (
>   Id int identity not null,
>   [Name] nvarchar(20) not null,
>     constraint Levels_PK primary key clustered(Id)
> ) -- Levels
>
> -- Roles
> create table dbo.Roles
> (
>   Id int identity not null,
>   [Name] nvarchar(40) not null,
>     constraint Roles_PK primary key clustered(Id)
> ) -- Roles
>
> -- Subjects
> create table dbo.Subjects
> (
>   Id int not null,
>   [Name] nvarchar(100) null,
>     constraint Subjects_PK primary key clustered(Id)
> ) -- Subjects
>
> -- Users
> create table dbo.Users
> (
>   Id int identity not null,
>   Approved bit not null constraint Users_Approved_DF default(0),
>   Comment nvarchar(2000) null,
>   Created datetime not null,
>   Email nvarchar(200) not null,
>   LastLock datetime not null,
>   LastLogin datetime not null,
>   LastPasswordChange datetime not null,
>   LastReset datetime not null,
>   Locked bit not null constraint Users_Locked_DF default(0),
>   [Password] varbinary(200) not null,
>   PasswordAttemptCount int not null,
>   PasswordAttemptStart datetime not null,
>   Salt varbinary(800) not null,
>   Updated datetime not null,
>   Username nvarchar(40) not null constraint Users_Username_U unique,
>     constraint Users_U primary key clustered(Id)
> ) -- Users
>
> -- Profiles
> create table dbo.Profiles
> (
>   Id int not null,
>   Birthday datetime not null,
>   City nvarchar(100) null,
>   DistrictId int not null,
>   GenderId int not null,
>   [Name] nvarchar(100) not null,
>   Newsletter bit not null constraint Users_Newsletter_DF default(0)
>         constraint Profiles_PK primary key clustered(Id),
>         constraint Profiles_Users_FK foreign key(Id) references dbo.Users(Id)
> on delete cascade on update cascade,
>         constraint Profiles_Districts_FK foreign key(DistrictId) references
> dbo.Districts(Id) on delete cascade on update cascade,
>         constraint Profiles_Genders_FK foreign key(GenderId) references
> dbo.Genders(Id) on delete cascade on update cascade
> )
>
> -- Professors
> create table dbo.Professors
> (
>   Id int not null,
>   CurriculumVitae nvarchar(max) null,
>   Mobile nvarchar(20) null,
>   Phone nvarchar(20) null
>         constraint Professors_PK primary key clustered(Id),
>         constraint Professors_Users_FK foreign key(Id) references
> dbo.Users(Id) on delete cascade on update cascade
> )
>
> -- ProfessorsLevels
> create table dbo.ProfessorsLevels
> (
>   ProfessorId int not null,
>   LevelId int not null,
>     constraint ProfessorsLevels_PK primary key clustered(ProfessorId,
> LevelId),
>     constraint ProfessorsLevels_Professors_FK foreign key(ProfessorId)
> references dbo.Professors(Id) on delete cascade on update cascade,
>         constraint ProfessorsLevels_Levels_FK foreign key(LevelId) references
> dbo.Levels(Id) on delete cascade on update cascade
> ) -- ProfessorsLevels
>
> -- ProfessorsSubjects
> create table dbo.ProfessorsSubjects
> (
>   ProfessorId int not null,
>   SubjectId int not null,
>     constraint ProfessorsSubjects_PK primary key
> clustered(ProfessorId, SubjectId),
>         constraint ProfessorsSubjects_Professors_FK foreign key(ProfessorId)
> references dbo.Professors(Id) on delete cascade on update cascade,
>         constraint ProfessorsSubjects_Subjects_FK foreign key(SubjectId)
> references dbo.Subjects(Id) on delete cascade on update cascade
> ) -- ProfessorsSubjects
>
> -- UsersRoles
> create table dbo.UsersRoles
> (
>   UserId int not null,
>   RoleId int not null,
>     constraint UsersRoles_PK primary key clustered(UserId, RoleId),
>     constraint UsersRoles_Users_FK foreign key(UserId) references
> dbo.Users(Id) on delete cascade on update cascade,
>         constraint UsersRoles_Roles_FK foreign key(RoleId) references
> dbo.Roles(Id) on delete cascade on update cascade
> ) -- UsersRoles
>
> What do you think?
>
> Thank You,
> Miguel

By the way, I mapped this database to EF4 and got the following:
http://www.flyondreams.net/Lab/EF4.jpg

Let me know if this makes sense ...

Would you improve it somehow?

For example, I am not sure if in tables Professors and Profiles since
they FK is the same as PK that I should name it UserId ... Or not?

Well, this is where I am so far ...
From: Erland Sommarskog on
shapper (mdmoura(a)gmail.com) writes:
> -- Profiles
> create table dbo.Profiles
> (
> Id int not null,
> Birthday datetime not null,
> City nvarchar(100) null,
> DistrictId int not null,
> GenderId int not null,
> [Name] nvarchar(100) not null,
> Newsletter bit not null constraint Users_Newsletter_DF default(0)
> constraint Profiles_PK primary key clustered(Id),
> constraint Profiles_Users_FK foreign key(Id) references dbo.Users(Id)
> on delete cascade on update cascade,
> constraint Profiles_Districts_FK foreign key(DistrictId) references
> dbo.Districts(Id) on delete cascade on update cascade,
> constraint Profiles_Genders_FK foreign key(GenderId) references
> dbo.Genders(Id) on delete cascade on update cascade
> )

Ahem, are you sure on all those ON DELETE CASCADE? If some decides to
delete a gender, should we then delete all profiles with that gender *and*
keep the users?

It does make sense to have ON DELETE CASCADE for the FK on Users; if
the user is deleted, the profile should go with it. But ON DELETE CASCADE
is rarely a good thing for references to lookup tables like Districts
or Genders.

Apart from that you need to review the casading properties, the model
makes sense to me.

--
Erland Sommarskog, SQL Server MVP, esquel(a)sommarskog.se

Links for SQL Server Books Online:
SQL 2008: http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
SQL 2005: http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
SQL 2000: http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: query question
Next: Need Help for a Join Query