sql-server – 在SQL Server中计划前提数据库相关
副问题[/!--empirenews.page--]
我有三种根基范例的实体:职员,企业和资产.每个资产可以由一个且仅一小我私人或企业拥有.每小我私人员和企业可以拥有0到多个资产.在Microsoft SQL Server中存储此类前提相关的最佳做法是什么? 我最初的打算是在Assets表中有两个可觉得空的外键,一个用于People,一个用于Business.个中一个值将为null,而另一个将指向全部者.我在这种配置中看到的题目是它必要应用措施逻辑才气被表明和执行.这真的是最好的办理方案照旧有其他选择? 办理要领先容SuperTypes和SubTypes我提议你行使超范例和子范例.起首,建设PartyType和Party表: CREATE TABLE dbo.PartyType ( PartyTypeID int NOT NULL identity(1,1) CONSTRAINT PK_PartyType PRIMARY KEY CLUSTERED Name varchar(32) CONSTRAINT UQ_PartyType_Name UNIQUE ); INSERT dbo.PartyType VALUES ('Person'),('Business'); 超 CREATE TABLE dbo.Party ( PartyID int identity(1,1) NOT NULL CONSTRAINT PK_Party PRIMARY KEY CLUSTERED,FullName varchar(64) NOT NULL,BeginDate smalldatetime,-- DOB for people or creation date for business PartyTypeID int NOT NULL CONSTRAINT FK_Party_PartyTypeID FOREIGN KEY REFERENCES dbo.PartyType (PartyTypeID) ); 亚型 然后,假如存在Person的独一列,则建设一个Person表,个中只包括: CREATE TABLE dbo.Person ( PersonPartyID int NOT NULL CONSTRAINT PK_Person PRIMARY KEY CLUSTERED CONSTRAINT FK_Person_PersonPartyID FOREIGN KEY REFERENCES dbo.Party (PartyID) ON DELETE CASCADE,-- add columns unique to people ); 假如存在对付企业而言独一的列,请建设一个仅包括以下内容的Business表: CREATE TABLE dbo.Business ( BusinessPartyID int NOT NULL CONSTRAINT PK_Business PRIMARY KEY CLUSTERED CONSTRAINT FK_Business_BusinessPartyID FOREIGN KEY REFERENCES dbo.Party (PartyID) ON DELETE CASCADE,-- add columns unique to businesses ); 用法和留意事项 最后,您的Asset表将如下所示: CREATE TABLE dbo.Asset ( AssetID int NOT NULL identity(1,1) CONSTRAINT PK_Asset PRIMARY KEY CLUSTERED,PartyID int NOT NULL CONSTRAINT FK_Asset_PartyID FOREIGN KEY REFERENCES dbo.Party (PartyID),AssetTag varchar(64) CONSTRAINT UQ_Asset_AssetTag UNIQUE ); 超范例Party表与子范例表Business和Person共享的相关是“一对零或一”.此刻,固然子范例凡是在另一个表中没有响应的行,但在这种计划中有也许让一个Party最终在两个表中.可是,您也许真的喜好这样:偶然一小我私人和一个企业险些可以交流.假如没有效,固然执行此操纵的触发器相等轻易,但最佳办理方案也许是将PartyTypeID列添加到子范例表中,使其成为PK&的一部门. FK,并在PartyTypeID上安排一个CHECK束缚. 此模子的利益在于,当您要建设对营业某职员具有束缚的列时,则将束缚配置为恰当的表而不是集会表. 另外,假如必要,在束缚上启用级联删除也许很有效,以及子范例表上的INSTEAD OF DELETE触发器,而是从超范例表中删除响应的ID(这可以担保不存在没有子范例行的超范例行).这些查询很是简朴,可以在整行存在或不存在的级别上事变,在我看来,这是对必要搜查列值同等性的任何计划的庞大改造. 另外,请留意,在很多环境下,您以为应该在个中一个子范例表中的列现实上可以组合在超范例表中,譬喻社会安详号.称之为TIN(纳税人辨认号码),它合用于企业和人. ID列定名 是否在Person表PartyID,PersonID或PersonPartyID中挪用列的题目是您本身的首选项,但我以为最好将这些PersonPartyID或BusinessPartyID称为容忍较长名称的本钱,这样可以停止两种范例的紊乱.譬喻,不认识数据库的人看到了BusinessID,而且不知道这是PartyID,可能看到PartyID,而且不知道它被外键限定在Business表中. 假如你想为Party和Business表建设视图,它们乃至可所以物化视图,由于它是一个简朴的内毗连,假如你真的云云倾向,你可以将PersonPartyID列重定名为PersonID(尽量我不肯意).假如它对你有很大的代价,你乃至可以在这些视图上建设INSTEAD OF INSERT和INSTEAD OF UPDATE触发器来处理赏罚两个表的插入,使得视图看起来像他们本身的表一样对许多应用措施. 使您的提议计划按原样运行 其它,我不想说起它,可是假如你想在你提出的计划中有一个束缚来逼迫只添补一个列,这里是代码: ALTER TABLE dbo.Assets ADD CONSTRAINT CK_Asset_PersonOrBusiness CHECK ( CASE WHEN PersonID IS NULL THEN 0 ELSE 1 END + CASE WHEN BusinessID IS NULL THEN 0 ELSE 1 END = 1 ); 可是,我不保举这种办理方案. 最后的设法 一个天然的第三个子范例是组织,从人和企业可以拥有成员资格的意义上来说.超范例和子范例也优雅地办理客户/员工,客户/供给商以及与您提出的相同的其他题目. 警惕不要夹杂“Is-A”和“Acts-As-A”.您可以通过查察订单表或查察订单计数来奉告集会是客户,而且也许基础不必要客户表.同样不要将身份与生命周期夹杂:租车也许最终会被出售,但这是生命周期的盼望,应该用列数据处理赏罚,而不是表存在 – 汽车不是以RentalCar和其后酿成了ForSaleCar,它一向都是Car.可能大概是RentalItem,大概企业也会租用其他对象.你大白了. 乃至也许不必要PartyType表.可以通过响应子范例表中存在行来确定集会范例.这还可以停止PartyTypeID与子范例表存在不匹配的隐藏题目.一种也许的实现是保存PartyType表,但从Party表中删除PartyTypeID,然后在Party表的视图中按照哪个子范例表具有响应的行返回正确的PartyTypeID.假如您选择应承派对成为两种子范例,则无效.然后,您只需僵持行使子范例视图,并知道BusinessID和PersonID的沟通值指向统一方. 进一步阅读这种模式 请参阅A Universal Person and Organization Data Model以得到更完备和理论上的处理赏罚. 我最近发明以下文章对付描写在数据库中建模担任的一些更换要领很有效.固然特定于Microsoft的Entity Framework ORM器材,但您无法在任何数据库开拓中自行实现这些器材: (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |