views:

82

answers:

6

I've taken over an application that has a SQL backend. There are multiple tables, but the two that I'm concerned about are these:

QAProfile
---------
ProfileID <pk> -int
ProfileName
SecurityGroups -varchar(max)


SecurityGroups
--------------
GroupID <pk> -int
GroupName

My issue is that the the SecurityGroups field is a comma delimited list of GroupID values.

So the Profile table looks like this:

-------------------------------------------- 
| ProfileID | ProfileName | SecurityGroups | 
-------------------------------------------- 
|    1      |     foo     |  ,1,13,34,56,  | 
-------------------------------------------- 
|    2      |     bar     |  ,4,13,29,56,  | 
-------------------------------------------- 

A profile can have muliple security groups and a security group can be on muliple profiles

Any suggestions on how to re-engineer this?

+1  A: 

Yes piece of cake you could just create a junction table like this:

ProfileSecurityGroups
---------------------
Id, <pk> -int
ProfileId <fk>,
SecurityGroupId <fk>
James
+4  A: 

Hi,
if it was me i loud do it like this

QAProfile
---------
ProfileID <pk> -int
ProfileName

SecurityGroups
--------------
GroupID <pk> -int
GroupName

QASecurityGroups
----------------
ProfileID<pk>
GroupID <pk>

Best Regards,
Iordan

IordanTanev
+9  A: 

It's good that you're looking to re-engineer this, since in general comma-delimited lists don't belong to SQL databases.

It looks like a simple junction table can replace the SecurityGroups column of the QAProfile table:

CREATE TABLE SecurityGroups_Profiles (
    GroupID     int    NOT NULL,
    ProfileID   int    NOT NULL,
    PRIMARY KEY (GroupID, ProfileID),
    FOREIGN KEY (GroupID) REFERENCES SecurityGroups (GroupID),
    FOREIGN KEY (ProfileID) REFERENCES QAProfile (ProfileID)
);
Daniel Vassallo
yours is nicer, you even added the FK's! I figured they could do that themselves.
Sage
I don't agree with the statement: "comma delimited lists don't belong to SQL database" seems a bit dogmatic - there certainly are circumstances where such a strategy is greatly beneficial for performance reasons.
James
@James: You have a point. Added "in general" to that sentence to be more accurate.
Daniel Vassallo
@Daniel Thanks!
zeroef
In this case the `SecurityGroups` column violates first normal form (a non-scalar data type faked using `VARCHAR(MAX)`) and there is no way of enforcing declarative referential integrity between the domain values (which are of type `INTEGER`).
onedaywhen
@onedaywhen: Yes, correct. That is solved by junction table.
Daniel Vassallo
+2  A: 
Create Table QAProfileSecurityGroup (
 ProfileID int,
 GroupID int,
 PRIMARY KEY ( ProfileID, GroupID)
)
Sage
+1  A: 
  • A new Table ProfileToGroup should be added:

    ProfileID GroupID

  • You will need to write a SQL script to parse out the list of groups and insert records into the new table for each Profile/Group combination.
  • Finally, the SecurityGroups column in the QAProfile table should be removed
Keith
+2  A: 
  • add table ProfileSecurityGroups
  • parse that string for each profile and add pairs to the table
  • change the app layer to use new structure
  • drop the SecurityGroups column from the Profile table

alt text

Damir Sudarevic
Way over the top gotta give you +1 for whipping up a diagram!
James