开发者

Sql Server - Foreign key referencing multiple columns one of which isn't in the source table

I've got a problem with foreign key. This is my DB structure (simplified):

Table 'Languages'

LanguageID - primary key
LanguageName - string (for example 'English')
..

Table 'Users'

UserID - primary key
LanguageID - byte (FK to Languages.LanguageID)
..

Table 'Localization'

LocalizationID - / compound primary key
LanguageID     - \ compound primary key (FK t开发者_运维知识库o Languages.LanguageID)
Data - string (for example 'My Program' in English)

Table 'UserLocalization'

UserLocalizationID - primary key
UserID - which user (FK to Users.UserID)
..
some other useful columns -> this table cannot be removed **EDITED**
..
LocalizationID - what string (FK to Localization.?) <- oops, not really because 
                                                       LanguageID is needed 
                                                       for FK to 'Localization' 

How to make a FK (or any other integrity check) in 'UserLocalization' to 'Localization'. Is it possible in this configuration ? Or is it not ok, and therefore some restructuralization (really ?) is needed ? If so how to accomplish it ?

Edit: A bit cleaned up for better clarity.


The simple answer is: if you have your table Localization like this:

LocalizationID - / compound primary key
LanguageID     - \ compound primary key (FK to Languages.LanguageID)
Data - string (for example 'My Program' in English)

and you want to add a foreign key to another table referencing this table, that foreign key needs to have both columns of your PK here at hand, so it could be:

Table 'UserLocalization'

UserLocalizationID - primary key
UserID - which user (FK to Users.UserID)
(LocalizationID, LanguageID) - FK to Localization

That's one of the downsides of compound primary keys - any FK referencing them must also include all columns of the compound PK - no exceptions / tricks / workarounds possible. With two columns, that's still doable, but with four, five, ten columns it gets really really messy. It also means any JOIN to that table must contain all common fields - and again, with two it's still ok, but with more, it gets really messy.

This is one of the reasons I would often consider adding an artificial surrogate key to tables where I only have a compound PK - just to simplify FK joins to it.


Get rid of the UserLocalization table. Use this SQL instead to find the localized strings for the users:

SELECT * FROM Users INNER JOIN Localization ON Users.LanguageID = Localization.LanguageID

All users with the same language need/have the same localization records, so you don't need to add any more integrity checks; you're doing all the checks already with the FKs on LanguageID in the Users and Localization tables.

If you want to find a specific user's localized data/strings just put a WHERE UserID = [Whatever] on the end of the SQL.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜