Ok, I am making a lot of assumptions (INT instead of VARCHAR(50) being one of them) with this answer, so feel free to correct me if needed. The problem with option B is that it introduces a new join to relate Users to Alerts without any real added benefit. If joining on the UserID, it is best to index the UserID, so you can utilize seeks for your joins.
For Option A, UserID will be the clustering key (index key for the clustered index) on the Users table. UserID will be a nonclustered index key on Alerts table. This will cost 16 bytes per Alert.
For Option B, UserID will be the clustering key on the Users table. UserId will probably be the clustering key in UserMap too, to make joining more efficient. UserKey (assuming this is an INT) would then be a nonclustered index key on the Alerts table. This will cost 4 bytes per Alert. And 20 bytes per UserMap.
Looking at the big picture, one relationship, for Option A, costs 16 bytes of storage, and involves 1 join operation. Whereas, one relationship, for Option B, costs 24 bytes of storage, and involves 2 join operations.
Furthermore, there are a possibility of 340,282,366,920,938,000,000,000,000,000,000,000,000 uniqueidentifiers and only 4,294,967,296 INTs. Implementing a uniqueidentifier to INT map for a this type of relationship could cause unexpected results when you start reusing INTs.
The only reason for creating this type map table, is if you plan on creating a Many to Many relationship between Users and Alerts.
Taking all of this into consideration, I would recommend Option A.
I hope this helps,
Matt
Best Answer
I've re-written your
CREATE TABLE
statements like this:Always specify the "schema" of the table; in the above example that is
dbo
- which is the default schema. Specifying the schema name removes confusion about what schema will contain the table. I've renamed theuf
column in theuf
table touf_name
to remove confusion when theuf
table is used in queries. You can name a column the same name as the table it appears in, but I would try not to do that.The
dbo.uf
table has aPRIMARY KEY
constraint which enforces uniqueness and makes the contents of the referenced column valid for use as a foreign key in other, related tables.The
dbo.carta
anddbo.cliente
tables haveFOREIGN KEY
references to thedbo.uf
table. This prevents inserting rows into those tables without a valid entry in thedbo.uf
table. This is commonly referred to as referential integrity and is an important principle in good database design.I've made all the columns
NOT NULL
since non-null values are easier to understand, especially when learning.Below, we're inserting data into the three tables in a way that shows how the foreign keys work. First, we'll insert two country names into the
dbo.uf
table:The results:
The
uf_id
column is used in the other two tables, instead of the actual name of the country itself:To join the three tables together, you use the
JOIN
clause, such as:which shows the following results:
Steve Stedman made a fantastic poster about the different kinds of
JOIN
statements, which is available here.