I have a tables Person and Address. A Person can have multiple Address records, so a simple 1..* relationship with Address having a field referencing 'Person ID'.
Now, for a given Person I wish to identify their 'default' or 'primary' Address.
I've came up with two ideas, but I'm not convinced about either. Before I decide, can anyone offer any comments with regards to potential issues I could face down the line with either option...
(a). Could have a 'Default Address ID' on Person which would store the ID of the default Address record. Possible pitfall here is that an Address not belonging to this Person could be set here, so would need an additional check constraint to prevent this.
(b). Could have a 'Default' flag on the Address table, but this has the possibility of allowing multiple selections, so would need further checks so that when setting the flag, it is also cleared on all records belonging to the same Person.
Any
In a One-To-Many relationship, one object is the "parent" and one is the "child". The parent controls the existence of the child. In a Many-To-Many, the existence of either type is dependent on something outside the both of them (in the larger application context).
These two are both ending with creating the same relationship as below: It means there is no difference in one-to-many or many-to-one, except the angle that you are reading that from. If you look at this from Stores table, you have a “one-to-many” relationship.
One-to-one relationships associate one record in one table with a single record in the other table. One-to-many relationships associate one record in one table with many records in the other table. Save this answer.
A one-to-many relationship is created if only one of the related columns is a primary key or has a unique constraint. In the relationship window in Access, the primary key side of a one-to-many relationship is denoted by a number 1. The foreign key side of a relationship is denoted by an infinity symbol.
I would go with (B) and then safeguard the setting of the default bit.
From reading your comments on your question I want to add that to enforce that there is always at least 1 address set with the default bit you just need to handle that in your stored procedure.
Something like:
for an insert:
DECLARE @IsDefault bit;
SET @IsDefault = 0;
IF NOT EXISTS (SELECT * from tblAddresses WHERE PersonID = @PersonID And Default = 1)
BEGIN
SET @IsDefault = 1;
END
INSERT INTO tblAddress (.... Default ... )
VALUES (... @IsDefault ... );
for an update:
IF (@Default = 1)
BEGIN
Update tblAddress
SET
tblAddress.Default = 0
FROM tblAddress
WHERE tblAddress.PersonID = @PersonID;
Update tblAddress
SET
tblAddress.Default = 1
WHERE ID = @AddressID;
END
ELSE
BEGIN
IF EXISTS (SELECT * FROM tblAddresses WHERE PersonID = @PersonID AND Default = 1 AND AddressID != @AddressID)
BEGIN
UPDATE tblAddresses
SET Default = 0
WHERE AddressID = @AddressID;
END
END
In addition, you could prevent this from your user interface as well, but it doesn't hurt to have an extra layer of protection in the DB.
Another option is (normalizing the data by) adding another table DefaultAddress
:
Person
------
PersonId
... other stuff
PRIMARY KEY (PersonId)
Address
-------
AddressId
PersonId
... other stuff
PRIMARY KEY (AddressId)
FOREIGN KEY (PersonId)
REFERENCES Person(PersonId)
DefaultAddress
--------------
AddressId
PersonId
PRIMARY KEY (AddressId)
UNIQUE KEY (PersonId) --- every person has (max) one default address
FOREIGN KEY (PersonId, AddressId)
REFERENCES Address(PersonId, AddressId)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With