Model one-to-many relationship in database - sql

I am trying to find a proper pattern to model one-to-many relationship from several tables to a common table.
EntityA, EntityB and other entities have one or many GenericInfo.
EntityA (0..1) ------ (1..N) GenericInfo
EntityB (0..1) ------ (1..N) GenericInfo
EntityC (0..1) ------ (1..N) GenericInfo
Option1: These entities are different so I cannot use a super table to model the relationships like
SuperEntity (S_Id pk)
EntityA (S_Id pk fk)
EntityB (S_Id pk fk)
GenericInfo (G_Id pk, S_id fk)
Option2: And I don't want to lose referential integrity by removing the foreign key constrain from the GenericInfo table.
EntityA (S_Id pk fk)
EntityB (S_Id pk fk)
GenericInfo (G_Id pk, unique_id non-fk)
Option3: I am currently using association tables for relationship mapping.
EntityA (A_Id pk)
EntityB (B_Id pk)
EntityAInfo(A_Id pk fk, G_Id pk fk)
EntityBInfo(B_Id pk fk, G_Id pk fk)
GenericInfo (G_Id pk)
I don't like this solution because too many tables have to be created in the database whose whole purpose is to preserve the links/relationships.
Option4: Another way I can think of is to create a mapping table with a single Id attribute like this,
EntityA (A_Id pk, I_id fk nullable)
EntityB (B_Id pk, I_id fk nullable)
InfoMapping(I_Id pk)
GenericInfo (G_Id pk, I_Id fk)
I'd love your expert opinion and input.
Thanks,
update
Vasek, thanks for your comment.
The problem I try to resolve is: How to establish object-relational mapping for an interface implementation which exposes a collection of objects?
We are using one table per class strategy for OR mapping. So each table in the example is mapped from a class. Suppose we have the following type definitions and tables (It is a pity I cannot post disgrams here)
public interface IGenericInfoProvider
{
GenericInfo [ ] GenericInfoArray {get;set;}
}
public class BaseClassForA {} --------------------------------------------- Table BaseEntityForA
public class BaseClassForB {} --------------------------------------------- Table BaseEntityForB
public class ClassA : BaseClassForA, IGenericInfoProvider {} --- Table EntityA
public class ClassB : BaseClassForB, IGenericInfoProvider {} --- Table EntityB
public class GenericInfo {} ---------------------------------------------------- Table GenericInfo
I am trying to model the one-to-many relationship between EntityA/EntityB and GenericInfo. This kind of relationships are pretty common in our domain model.
Option1 is not considered beacuse this leads to create a supertable to include all the ids from lots of tables and it doesn't make any sense in OO world.
Option2 is unacceptable because of referential integrity.
Option3 is the pattern I currently use.
I am considering Option4 but not sure if it is an approach in the right direction.

I am not sure what you wish to achieve, but I suppose it might be useful to try to use some database design tool to create the structure with tables, primary/foreign/alternate keys, compound keys, relationships etc. A picture is worth a thousand words :) and you can create various designs quickly, generate SQL code and think about how to store sample data.
For me the first scenario (Option 3) seems to represent M:N relationships. The second scenario (Option 4) represents different scenario - different referential integrity and therefore the two scenarios are not comparable.
Try to create sample databases, insert sample records and write queries.

Your current solution is the correct solution. It is the vbbest way to preserve data integrity which is the single most critical function of a database. Making more tables is something that should not even be a design consideration.

Related

SQL relationship between a primary key column and the same column

In an existing SQL Server database, someone has defined the following:
Table Customer has a CustomerID column which is also identity. Then they have defined a relationship where Customer.CustomerID is primary key and Customer.CustomerID is also foreign key. I.e. the relationship points back to the same table and same column.
What is the purpose of this? Seems entirely pointless to me, so I plan to remove this relationship from the DB.
The relation is called a recursive association or reflexive relationship, you will need this type of relationship when you need to present a relationship between two or more elements of the same type.
For example: for presenting a relationship between employees, you could create two tables Employee and Manager. But because the manager is also an employee, you won't need two tables. So we create a recursive association that point for the same entity.
More about recursive association
UPDATE
Setting a column as PK and FK at the same time could also represent the concept of inheritance.
For example:
class Person {
int ID;
string name;
}
class Customer extends Person {
String workPlace;
}
That would result the tables Person and Customer as listed below:
Person
------------
int id (PK)
string name
Employee
--------------
int id (PK, FK)
string workPlace

What is the necessity of junction tables?

I have implemented the following ways of storing relational topology:
1.A general junction relation table:
Table: Relation
Columns: id parent_type parent_id parent_prop child_type child_id child_prop
On which joins are not generally capable of being executed against by most sql engines.
2.Relation specific junction tables
Table: Class2Student
Columns: id parent_id parent_prop child_id child_prop
On which joins are capable of being executed against.
3.Storing lists/string maps of related objects in a text field on both bidirectional objects.
Class: Class
Class properties: id name students
Table columns: id name students_keys
Rows: 1 "history" [{type:Basic_student,id:1},{type:Advanced_student,id:3}]
To enable joins by the sql engines, it would be possible to write a custom module which would be made even easier if the contents of students_keys was simply [1,3], ie that a relation was to the explicit Student type.
The questions are the following in the context of:
I fail to see what the point of a junction table is. For example, I fail to see that any problems the following arguments for a junction table claim to relieve, actually exist:
Inability to logically correctly save a bidirectional relations (eg
there is no data orphaning in bidirectional relations or any
relations with a keys field, because one recursively saves and one can enforce
other operations (delete,update) quite easily)
Inability to join effectively
I am not soliciting opinions on your personal opinions on best practices or any cult-like statements on normalization.
The explicit question(s) are the following:
What are the instances where one would want to query a junction table that is not provided by querying a owning object's keys field?
What are logical implementation problems in the context of computation provided by the sql engine where the junction table is preferable?
The only implementation difference with regards to a junction table vs a keys fields is the following:
When searching for a query of the following nature you would need to match against the keys field with either a custom indexing implementation or some other reasonable implementation:
class_dao.search({students:advanced_student_3,name:"history"});
search for Classes that have a particular student and name "history"
As opposed to searching the indexed columns of the junction table and then selecting the approriate Classes.
I have been unable to identify answers why a junction table is logically preferable for quite literally any reason. I am not claiming this is the case or do I have a religious preference one way or another as evidenced by the fact that I implemented multiple ways of achieving this. My problem is I do not know what they are.
The way I see it, you have have several entities
CREATE TABLE StudentType
(
Id Int PRIMARY KEY,
Name NVarChar(50)
);
INSERT StudentType VALUES
(
(1, 'Basic'),
(2, 'Advanced'),
(3, 'SomeOtherCategory')
);
CREATE TABLE Student
(
Id Int PRIMARY KEY,
Name NVarChar(200),
OtherAttributeCommonToAllStudents Int,
Type Int,
CONSTRAINT FK_Student_StudentType
FOREIGN KEY (Type) REFERENCES StudentType(Id)
)
CREATE TABLE StudentAdvanced
(
Id Int PRIMARY KEY,
AdvancedOnlyAttribute Int,
CONSTRIANT FK_StudentAdvanced_Student
FOREIGN KEY (Id) REFERENCES Student(Id)
)
CREATE TABLE StudentSomeOtherCategory
(
Id Int PRIMARY KEY,
SomeOtherCategoryOnlyAttribute Int,
CONSTRIANT FK_StudentSomeOtherCategory_Student
FOREIGN KEY (Id) REFERENCES Student(Id)
)
Any attributes that are common to all students have columns on the Student table.
Types of student that have extra attributes are added to the StudentType table.
Each extra student type gets a Student<TypeName> table to store its specific attributes. These tables have an optional one-to-one relationship with Student.
I think that your "straw-man" junction table is a partial implementation of an EAV anti-pattern, the only time this is sensible, is when you can't know what attributes you need to model, i.e. your data will be entirely unstructured. When this is a real requirment, relational databases start to look less desirable. On those occasions consider a NOSQL/Document database alternative.
A junction table would be useful in the following scenario.
Say we add a Class entity to the model.
CREATE TABLE Class
(
Id Int PRIMARY KEY,
...
)
Its concievable that we would like to store the many-to-many realtionship between students and classes.
CREATE TABLE Registration
(
Id Int PRIMARY KEY,
StudentId Int,
ClassId Int,
CONSTRAINT FK_Registration_Student
FOREIGN KEY (StudentId) REFERENCES Student(Id),
CONSTRAINT FK_Registration_Class
FOREIGN KEY (ClassId) REFERENCES Class(Id)
)
This entity would be the right place to store attributes that relate specifically to a student's registration to a class, perhaps a completion flag for instance. Other data would naturally relate to this junction, pehaps a class specific attendance record or a grade history.
If you don't relate Class and Student in this way, how would you select both, all the students in a class, and all the classes a student reads. Performance wise, this is easily optimised by indices on key columns.
When a many-to-many realtionships exists without any attributes I agree that logically, the junction table needn't exist. However, in a relational database, junction tables are still a useful physical implmentaion, perhaps like this,
CREATE TABLE StudentClass
(
StudentId Int,
ClassId Int,
CONSTRAINT PK_StudentClass PRIMARY KEY (ClassId, StudentId),
CONSTRAINT FK_Registration_Student
FOREIGN KEY (StudentId) REFERENCES Student(Id),
CONSTRAINT FK_Registration_Class
FOREIGN KEY (ClassId) REFERENCES Class(Id)
)
this allows simple queries like
// students in a class?
SELECT StudentId
FROM StudentClass
WHERE ClassId = #classId
// classes read by a student?
SELECT ClassId
FROM StudentClass
WHERE StudentId = #studentId
additionaly, this enables a simple way to manage the relationship, partially or completely from either aspect, that will be familar to relational database developers and sargeable by query optimisers.

SQL - Should I use a junction table or not?

I am creating a new SQL Server 2008 database. I have two two tables that are related.
The first table looks like this:
BRANDS // table name
BrandID // pk
BrandName // varchar
The second table looks like this:
MODELS // table name
ModelID // pk
ModelDescription // varchar
Every brand will have at least one model and every model will belong to only one brand.
The question is, should I create a junction table like this
BRANDS_MODELS // table name
RecordID // pk
BrandID
ModelID
Or should I modify the MODELS table to include the BrandID like this
MODELS // table name
BrandID //
ModelID // pk
ModelDescription // varchar
Thanks!
If a model belongs to only one brand then you can put the FK to brand on the model table (your second approach). The first way, with the junction table, is for a many-to-many relation.
Based on what you've said so far, I would leave out the junction table and use an ordinary foreign key in the MODELS table.
But if a model could move brands and you needed to maintain a current junction and history, a junction table has advantages over keeping history of the entire MODELS row when just a foreign key changes. Also if other things exist which might be associated with the relationship "entity" more than the MODEL entity it might make more sense to have a junction table. You can always make a unique constraint on ModelID in the junction table to ensure that the same model is not linked to multiple brands. So although a junction table is required to effectively implement a many-to-many relationship, it can also be useful for one-to-many relationships where that relationship itself has attributes.
Junction tables are used for many-to-many relationships which does not seem to be a good fit here.
For example, you would not want to enable the creation of a Honda Civic and a Toyota Civic. That's an example of car's make/model relationship but should fit your brand/model relationship.

relationships in Sql

I know how to create one to many, many to many relationships in SQL Server, but is it possible to create one to one relationship? And is it possible to create 1 to 0 or 1 relationship?
Yes, just put PRIMARY KEYs of both entities into a link table, defining a UNIQUE key on both entities:
myrel(entityA, entityB, UNIQUE(entityA), UNIQUE(entityB))
Thus, if entityA = 1 is related to entityB = 2:
entityA entityB
1 2
, you can relate neither entityA = 1 to any other entityB, nor an entityB = 2 to any other entityA.
If you relation is symmetrical (i. e. entityA and entityB belong to same domain and relating entityA to entityB also means relating entityB to entityA), then define an additional CHECK constrant:
entityA entityB
UNIQUE(entityA)
UNIQUE(entityB)
CHECK(entityA < entityB)
and transform the normalized relation to a canonical one with this query:
SELECT entityA, entityB
FROM myrel
UNION
SELECT entityB, entityA
FROM myrel
This is a (0-1):(0-1) relation.
If you want it to be a 1:1 relation, define this table to be a domain for both entityA and entityB:
myrel(entityA, entityB, UNIQUE(entityA), UNIQUE(entityB))
A(id, PRIMARY KEY(id), FOREIGN KEY(id) REFERENCES myrel (entityA))
B(id, PRIMARY KEY(id), FOREIGN KEY(id) REFERENCES myrel (entityB))
By removing the FOREIGN KEY from either table's definition, you change the corresponding part of the relationship from 1 to (0-1).
Two ways:
1) a pk-pk 1:1 relationship. Table A and B have both a PK. Create an FK from the B PK to the PK of A. This makes 'B' the FK side of the 1:1 relationship
or
2) an FK/UC-PK 1:1 relationship. Table A has a PK and table B has a foreign key to A, but the FK in B is not on the PK of B. Now create a UC on the FK field(s) in B.
Yes, just make the Primary or alternate Key in the dependant table a Foreign Key to the Primary Key in the parent Table.
It's fun but it my favorite questions on interview.
So You have table A, B corresponding each of them has primary key A_ID, B_ID. Add foreign key to any. Let it be B: A_REF, so you just need add unique constraint onto A_REF.
Yes
TableA
id PK
TableB
id PK FK TableA

fluent NHibernate one-to-one relationship?

I have a problem with one-to-one relationships in the fluent nHibernate.
I have the following relational table from the AdventureWorks2008 database.
BusinessEntity (Table)
BusinessEntityId Int (PK, Identity)
Person (Table)
BusinessEntityId int (PK, Reference with BusinessEntity table)
FullName varchar(255)
The relationship between BusinessEntity table and Person table is one-to-one.
How do I map fluently without any extra field like "Id" in the Person table?
There should be 2 class one for Person and another for BusinessEntity, or an appropriate model to best describe the above relation.
Thanks,
Ashraf.
presuming your Person mapping is pretty standard, the way you do this is by saying:
Id(x => x.BusinessEntityId)
.GeneratedBy.Foreign("BusinessEntity");
on the Person class.
This presumes that your Person class has a property called BusinessEntity which is of type BusinessEntity.
You'll also need to map BusinessEntity to Person with constrained set to true (to say that they primary key of Person is a foreign key reference to BusinessEntity).
The key thing is the GeneratedBy.Foreign() to say that your identity is generated by a link to another class.