我试图找出将这些表联系在一起的最佳方法。假设我有以下表格:
每个表中的每一行都可以有多个与之关联的电子邮件地址,因此我想要一个单独的表并将其关联回来。
是否存在让单个表(tblEmail)与每个表相关的方法。我想到在每个父表中使用uniqueidentifier字段并将其用作电子邮件表中的键。它将保证独一无二。我只是无法在电子邮件表中创建FK以保持完整性。这是可以管理的。
有没有一种奇特的方法可以做到这一点?我在SQL 2008 R2中创建这些表。
谢谢 卡尔
答案 0 :(得分:2)
这是SQL的核心部分。在适当的关系设计中,您不会将电子邮件地址与群体,群组或资源相关联 - 您将人员,群组和资源与电子邮件相关联。
所以,使用电子邮件表:
CREATE TABLE dbo.tblEmail (
emailID int IDENTITY PRIMARY KEY,
email varchar(500)
)
如果您每个实体只需要一封电子邮件,则只需在每个其他字段中插入一个emailID
,这些字段可能需要发送电子邮件。
ALTER TABLE dbo.tblPerson
ADD emailID int REFERENCES dbo.tblEmail(emailID);
ALTER TABLE dbo.tblGroup
ADD emailID int REFERENCES dbo.tblEmail(emailID);
ALTER TABLE dbo.tblResource
ADD emailID int REFERENCES dbo.tblEmail(emailID);
如果每个实体需要多个电子邮件地址,则需要插入一个附加表,以便将该组电子邮件地址插入特定地址。 (除非您有技术上的理由单独处理地址,否则我不会这样做,例如批量电子邮件系统,如果有人使用相同的电子邮件供自己使用和组织的使用,您希望避免重复。)
CREATE TABLE dbo.tblEmail (
emailID int IDENTITY PRIMARY KEY
)
CREATE TABLE dbo.tblEmailAddress (
eAddrID IDENTITY PRIMARY KEY,
eAddr varchar(500)
)
CREATE TABLE dbo.tblEmailSet (
emailID int REFERENCES dbo.tblEmail(emailID),
eAddrID int REFERENCES dbo.tblEmailAddresses(eAddrID),
)
为了将所有电子邮件列表返回给名为“Smith”的任何人员,组或资源,您将运行以下查询:
SELECT DISTINCT A.eAddr
FROM (
SELECT emailID FROM dbo.tblPerson WHERE Name = 'Smith'
UNION
SELECT emailID FROM dbo.tblGroup WHERE Name = 'Smith'
UNION
SELECT emailID FROM dbo.tblResource WHERE Name = 'Smith'
) AS PGR
INNER JOIN dbo.tblEmailSet AS S
ON PGR.emailID = S.emailID
INNER JOIN dbo.tblEmailAddress AS A
ON S.eAddrID = A.eAddrID
那个丑陋的UNION
,顺便说一句,这是你真的不想这样做的原因之一,除非你有技术上需要唯一地检索数据。虽然我偶尔会做这种多对多的连接,但在这个特殊情况下,它有点像“代码味道”,而不是跟踪“人物”,“群组”和“资源“,您应该使用”类型“指示符跟踪”联系人“,以告知联系人是个人,组还是资源。
(或者你可能永远不需要抓住一堆电子邮件地址,只需要一张电子邮件表就可以检查白名单......)
答案 1 :(得分:0)
虽然尝试使用带有ParentType
(人员/组/资源)和ParentID
的单个电子邮件表可能很诱人,但这很危险并且意味着您无法定义关系在SQL中(除非有一些我不知道的功能?)。
如果你想在SQL中拥有引用完整性,你真的需要创建3个表,每个父表一个表。
CREATE TABLE dbo.PersonEmail (
ID int IDENTITY PRIMARY KEY,
PersonID int,
EmailAddress varchar(500)
)
CREATE TABLE dbo.GroupEmail (
ID int IDENTITY PRIMARY KEY,
GroupID int,
EmailAddress varchar(500)
)
CREATE TABLE dbo.ResourceEmail (
ID int IDENTITY PRIMARY KEY,
ResourceID int,
EmailAddress varchar(500)
)
如果您认为可以将您的电子邮件表扩展为稍后包含DisplayName,可能还包括BounceCount和其他人,请为电子邮件创建一个表并创建多对多连接表以将其链接到人员/组/资源。
请注意,编辑可能会影响多个链接,您必须决定如何处理。
答案 2 :(得分:0)
因此,您希望每个人/组/资源可能有多个电子邮件,并且您希望将所有这些电子邮件放在一个表中,我是否正确?
为此,我将创建一个表dbo.EmailAddress,例如:
CREATE TABLE dbo.EmailAddress
(
EmailID BIGINT IDENTITY(1,1) NOT NULL PRIMARY KEY
,EmailAddress VARCHAR(250) NOT NULL
CONSTRAINT UK_EmailAddress UNIQUE(EmailAddress) --to ensure that you never insert twice the same email address
)
然后我会使用另一个表创建您的人/组/资源与电子邮件之间的关系:
CREATE TABLE dbo.EmailAddressParentXRef
(
EmailID INT NOT NULL REFERENCES dbo.EmailAddress(EmailID)
,ParentTypeID INT NOT NULL
,PersonID INT NULL REFERENCES dbo.tblPerson(PersonID)
,GroupID INT NULL REFERENCES dbo.tblGroup(GroupID)
,ResourceID INT NULL REFERENCES dbo.tblResource(ResourceID)
CONSTRAINT UK_EmailID_ParentTypeID UNIQUE(EmailID,ParentTypeID) --to make sure you don't put the same EmailID for the same type of Parent (e.g. EmailID=12 twice for an Account)
)
在加载数据时,您会有参照完整性+一些检查以避免重复。请注意,我没有检查以确保您实际填写PersonID,GroupID或ResourceID。这可以以不同的方式添加,但是如果你理解了这个表的原理,你就不应该加载没有那些引用的任何行(或者它们只是没用)。
可以在此基础上添加更多检查,以处理加载数据时可能创建的每种类型的重复/错误,但您明白了。
答案 3 :(得分:0)
Each row in each of these tables can have multiple email addresses associated with them
你能给出每个表的一个例子吗。电子邮件是多个?