在SQL Server中创建具有非唯一列的外键
我正在处理一个同时包含汽车和车主的表(表在SQL Server中创建具有非唯一列的外键,sql,sql-server-2008,Sql,Sql Server 2008,我正在处理一个同时包含汽车和车主的表(表CO)。我正在创建另一个表,其中包含用户可以通过GUI分配给的所有者属性(tableOwnerAttributes)。我的问题在于所有者不是唯一的,因为我使用的是SQL Server,所以无法在其上创建外键。表中有一个id,但它将汽车和车主作为一个整体进行标识 我绕过这个问题的想法是创建一个包含不同所有者的新表(表Owners),然后向表CO添加一个触发器,该触发器将使用任何更改更新所有者。然后,我可以使用表OwnerAttributes为我的OwnerA
CO
)。我正在创建另一个表,其中包含用户可以通过GUI分配给的所有者属性(tableOwnerAttributes
)。我的问题在于所有者不是唯一的,因为我使用的是SQL Server,所以无法在其上创建外键。表中有一个id,但它将汽车和车主作为一个整体进行标识
我绕过这个问题的想法是创建一个包含不同所有者的新表(表Owners
),然后向表CO
添加一个触发器,该触发器将使用任何更改更新所有者。然后,我可以使用表OwnerAttributes
为我的OwnerAttributes
表解决我的问题
我想回答的问题是,是否有更好的方法
我使用的是一个预先存在的数据库,它被一个旧的应用程序大量使用。将该应用程序连接起来,以便为车主和汽车使用表CO
。还有其他几个表使用了CO
表。我希望我可以将表分为所有者
和汽车
,但公司不希望我把所有的时间都花在这上面,因为我还需要向应用程序添加更多的功能。你应该创建所有者表、汽车表、所有者卡表(如果一个人可以拥有几辆汽车的话)。所有者表包含描述所有者(所有者属性)的字段。您应该创建所有者表、汽车表、所有者卡表(如果用户可以拥有几辆汽车)。所有者表包含描述所有者(所有者属性)的字段。您对所有者表的看法是正确的!您的问题是因为您的模式没有规范化。事实上,您在一张表(您的表CO)中存储了两件东西(汽车和车主)
您应该创建一个所有者表,这是正确的,但是您应该完全从CO表中删除所有者信息,并将其替换为所有者表的外键
所以你想要这样的东西:
CREATE TABLE Owner (
ownerID int not null primary key indentity(1,0),
FirstName varchar(255),
LastName varchar(255),
/* other fields here */
)
GO
CREATE TABLE Car
carID int not null primary key identity(1,0),
ownerID int not null references Owner(ownerID),
/* other fields go here */
GO
/* a convenience, read only view to replace your old CAR OWNER table */
CREATE VIEW Car_Owner AS
SELECT c.*, o.FirstName, o.LastName FROM Car c INNER JOIN Owner o ON c.ownerID = o.ownerID
现在,您已经在SQL中正确地规范化了所有内容。一个视图将车主作为一件事返回到一个伪表中
但真正的答案是,规范化您的模式。让SQL做它最擅长的事情(将事情与其他事情联系起来)。将这两件事放在一张桌子上只会导致更多的问题,比如你在下游遇到的问题
希望这个答案看起来很有帮助,而不是居高临下,这正是我想要的!我通过艰苦的努力了解到,这种方法(规范化所有内容,让数据库做一些额外的工作来检索/显示/插入它)是最后唯一有效的方法。您对Owners表的想法是正确的!您的问题是因为您的模式没有规范化。事实上,您在一张表(您的表CO)中存储了两件东西(汽车和车主)
您应该创建一个所有者表,这是正确的,但是您应该完全从CO表中删除所有者信息,并将其替换为所有者表的外键
所以你想要这样的东西:
CREATE TABLE Owner (
ownerID int not null primary key indentity(1,0),
FirstName varchar(255),
LastName varchar(255),
/* other fields here */
)
GO
CREATE TABLE Car
carID int not null primary key identity(1,0),
ownerID int not null references Owner(ownerID),
/* other fields go here */
GO
/* a convenience, read only view to replace your old CAR OWNER table */
CREATE VIEW Car_Owner AS
SELECT c.*, o.FirstName, o.LastName FROM Car c INNER JOIN Owner o ON c.ownerID = o.ownerID
现在,您已经在SQL中正确地规范化了所有内容。一个视图将车主作为一件事返回到一个伪表中
但真正的答案是,规范化您的模式。让SQL做它最擅长的事情(将事情与其他事情联系起来)。将这两件事放在一张桌子上只会导致更多的问题,比如你在下游遇到的问题
希望这个答案看起来很有帮助,而不是居高临下,这正是我想要的!我了解到,这种方法(规范化一切,让数据库做一些额外的工作来检索/显示/插入它)是最后唯一可行的方法。听起来像是在使用实体属性值模式设计[OwnerAttribute]表。也许你可以在这里了解一下这种方法的优缺点:我也写了一篇关于它的博客文章。不确定它是否与op相关,但对于搜索EAV的任何人来说,它可能值得一看(特别是随后的讨论):听起来您正在使用实体属性值模式设计[OwnerAttribute]表。也许你可以在这里了解一下这种方法的优缺点:我也写了一篇关于它的博客文章。不确定它是否与op相关,但对于搜索EAV的任何人来说,它可能值得一看(特别是随后的讨论):如果一辆车只能由一个人拥有(似乎是当前状态),您不需要OwnerCar表,只需将fk_owner添加到Car表我使用的是一个现有数据库,它被一个旧的应用程序大量使用。该应用程序被连接起来,以便为车主和汽车使用表格CO。我希望我可以将表拆分为车主和汽车,但公司不希望我把所有的时间都花在这方面。您可以创建上面的结构,然后使用CO表的旧名称创建一个视图。旧代码仍然有效(但现在正在引用视图),并且可以继续正确地更改。如果一辆车只能由一个人拥有(似乎是当前状态),则不需要OwnerCar表,只需将fk_owner添加到Car表中即可。我正在使用一个旧应用程序大量使用的现有数据库。该应用程序被连接起来,以便为车主和汽车使用表格CO。我希望我可以将表拆分为车主和汽车,但公司不希望我把所有的时间都花在这方面。您可以创建上面的结构,然后使用CO表的旧名称创建一个视图。旧的代码仍然有效(但现在正在引用视图),继续下去,你可以适当地改变事情。在与该公司的首席开发人员讨论后,决定采用这种方式,但由于时间限制,我不会实施这种方式。修复和测试应用程序所需的时间太长,而gai太少