PRIMARY KEYs与UNIQUE约束

Jon*_*ood 5 sql-server foreign-keys sql-server-2008

Alexander Kuznetsov文章中,他提供了以下代码片段:

CREATE TABLE dbo.Vehicles(
    ID INT NOT NULL, 
    [Type] VARCHAR(5) NOT NULL,
    CONSTRAINT Vehicles_PK PRIMARY KEY(ID),
    CONSTRAINT Vehicles_UNQ_ID_Type UNIQUE(ID, [Type]),
    CONSTRAINT Vehicles_CHK_ValidTypes CHECK([Type] IN ('Car', 'Truck'))
);
Run Code Online (Sandbox Code Playgroud)

这个片段为我提出了一些问题.

  1. 为什么要包括IDType在唯一约束?如果只是ID唯一的,那么两列的组合也将始终是唯一的.

  2. 此外,我知道如何设置主键并指定它是否在SSMS中是唯一的.但是,如何在一列上指定主键,并对列组合进行唯一约束?这会创建两个索引吗?

这是因为我试图实现类似的代码,它不会创建复合主键,我得到以下错误.所以我试图更好地理解这些代码.

表'MyTable'中的列与现有主键或UNIQUE约束不匹配.


编辑

我能够通过简单地创建一个复合主键来实现这一点MyTable.实际的表定义如下所示.再次,这是有效的.但它与上面引用的代码不同.而且我不确定如果我以其他方式做到这一点会更好.

CREATE TABLE [dbo].[MessageThread](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [MessageThreadType] [int] NOT NULL,
    CONSTRAINT [PK_MessageThread_1] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC,
        [MessageThreadType] ASC
    ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[MessageThread]  WITH CHECK ADD  CONSTRAINT [CK_MessageThread_ValidType] CHECK  (([MessageThreadType]=(2) OR [MessageThreadType]=(1)))
GO

ALTER TABLE [dbo].[MessageThread] CHECK CONSTRAINT [CK_MessageThread_ValidType]
GO
Run Code Online (Sandbox Code Playgroud)

a1e*_*x07 7

在我的理解中,唯一约束的原因ID,[Type]是让细节表ID,[Type]作为外键引用.通常,父表需要对用于外键的列具有唯一约束.例如,问题中的表可以有2个详细信息表:

CREATE TABLE dbo.CARS( 
....
vehicle_id INT NOT NULL,
[Type] VARCHAR(5) NOT NULL,
CONSTRAINT CAR_CHK_TYPE CHECK [Type]='Car',
CONSTRAINT CAR_FK_VEHICLE FOREIGN KEY (vehicle_id,[Type]) REFERENCES Vehincle(id,[Type]));

CREATE TABLE dbo.TRUCKS( 
....
vehicle_id INT NOT NULL,
[Type] VARCHAR(5) NOT NULL,
CONSTRAINT CAR_CHK_TYPE CHECK [Type]='Truck',
CONSTRAINT CAR_FK_VEHICLE FOREIGN KEY (vehicle_id,[Type]) REFERENCES Vehincle(id,[Type]));
Run Code Online (Sandbox Code Playgroud)

这种方式Cars只有关于Car类型的细节,而TRUCKS只有约Truck.

例如,这种设计用于避免多态关系

CREATE TABLE dbo.VEHICLE (
...,
ref_id INT NOT NULL,
-- PK of 'master' table
ref_name VARCHAR(20) NOT NULL, 
-- here we put 'truck' or 'car', so we virtually have 2 parents; 
-- in this case we cannot use FK constraint, the only thing that may 
-- somehow enforce the logical constraint is writing a trigger
Run Code Online (Sandbox Code Playgroud)

更新

您更新的表定义对我来说很好.我想样本表最初是为Oracle设计的,然后移植到SQLServer.在Oracle中,该唯一约束和主键可以使用相同的索引,因此同时具有PK和Unique约束不会受到惩罚.


Aar*_*and 7

1:我不确定给定模式的具体目的.但请注意,可以出于多种原因应用唯一约束,最常见的原因是:(a)强制执行唯一性;(b)为优化程序提供更多信息以作出基础决策.

2:唯一约束不会创建两个索引.它创建一个索引,其中一列作为前导键列.它强制执行两者的唯一性.因此对a,b的唯一约束可能有:

a    b    
---- ----
1    1
1    2
2    1
2    2
Run Code Online (Sandbox Code Playgroud)

请注意,这两列都不会单独强制实现唯一性.我不是在SSMS中使用表设计器的忠实粉丝(它有大量的bug并且不支持所有功能)但是这里是如何做到的:

a)右键单击网格并选择 Indexes/Keys...

b)使用Columns网格中的[...]按钮选择多个列

c)Type改为Unique Key

d)Name如果需要,改变

在此输入图像描述

这是一个已经有主键的表的示例.如果我想要,我可以添加一个或多个唯一索引:

在此输入图像描述