我有一个表,用于存储名为dbo.Vendor
的供应商的信息。它有这样的字段:
1. VendorID
2. VendorName
3. VendorType
4. AddressLine1
5. EMail
6. Telephone
7. and so on....
此信息对所有供应商都是通用的。但是根据供应商的类型(VendorType
字段),我需要收集更多具体信息。例如,作为慈善机构的供应商将拥有慈善机构编号,但作为律师的供应商将拥有某种合法注册编号。如果供应商是电影院,那么我可能需要了解当然不适用于其他供应商的座位容量。
我是否真的必须为这些不同的供应商创建一个唯一的表格,例如dbo.VendorLaw
,dbo.VendorCinema
。或者,我是否可以在主dbo.Vendor
表中创建所有可能的字段,并将NULL
值保留在该字段不适用于该供应商的位置?这当然打破了规范化规则。
答案 0 :(得分:1)
根据每个供应商类型需要多少额外可选信息的范围,我将创建另外两个表:一个存储所有不同类型的附加信息的参考表,以及一个存储所有记录的表(和链接到主表。)
CREATE TABLE schema.VendorAdditionalInfo (
autoId serial NOT NULL,
vendorId int,
vendorInfoId int,
vendorInfoText varchar
);
然后创建参考表:
CREATE TABLE schema.VendorInfo (
vendorInfoId serial NOT NULL,
vendorType int,
vendorInfoName text
)
这样,您可以根据供应商的类型在VendorAdditionalInfo中创建任意数量的记录。
编辑:您输入的信息示例:
INSERT INTO schema.VendorInfo (vendorType, vendorInfoName)
VALUES
(1, 'Lawyer Registration Number'),
(2, 'Nurse ID Number'),
(3, 'Hot Dog Business License')
然后,对于您的记录表,您将输入您的信息:
INSERT INTO schema.VendorAdditionalInfo (vendorId, vendorInfoId, vendorInfoText)
VALUES
(10, 1, 'LAW13245'),
(11, 2, 'NURSE234234'),
(12, 1, 'LAW56156'),
(13, 3, 'HOTDOGBUSINESSLIC23')
基本上 - 文本字段是每个附加信息类型唯一的字段。
答案 1 :(得分:1)
我会创建其他表格。这允许您根据供应商类型轻松实施null /非null(和其他)约束 - 您甚至可以在(VendorID,VendorType)上的现有表中创建超级密钥,并在每个供应商特定列中创建计算列以确保那个,例如只有Cinema供应商在VendorCinema表中有条目。
CREATE TABLE Vendors (
VendorID int IDENTITY(-47,1) not null,
VendorName varchar(19) not null,
VendorType varchar(11) not null,
AddressLine1 varchar(35) not null,
EMail varchar(312) null,
Telephone varchar(15) null,
constraint PK_Vendors PRIMARY KEY (VendorID),
constraint UQ_Vendor_Types UNIQUE (VendorID,VendorType),
constraint CK_Vendor_Types CHECK (VendorType in ('Law','Cinema'))
)
和
CREATE TABLE CinemaVendors (
VendorID int not null,
VendorType as CONVERT(varchar(11),'Cinema') persisted,
Seating int not null,
BruceWillisMovies int not null,
constraint PK_CinemaVendors PRIMARY KEY (VendorID),
constraint FK_CinemaVendors_Vendors FOREIGN KEY
(VendorID,VendorType)
references Vendors (VendorID,VendorType),
constraint CK_BruceWillisMovies CHECK (BruceWillisMovies > 3)
)
在单独的表中,这比在一个表中拥有大量可为空的列然后尝试强制执行所有实际约束要容易得多。
这也解决了EAV模式的问题 - 我们希望为电影供应商存储int
,我们确信实际存储了int
。
(你可以选择是否同时根据VendorID
列在上述两个表之间声明一个外键。有时候我会这样做,有时我不这样做。这是“真正的”外键,但我们使用上面的第二列确保只有Cinema
个供应商最终进入CinemaVendors
表格