SQL Server 2008:如何将FK设置为​​PK?

发布于 2024-10-08 20:11:44 字数 169 浏览 6 评论 0原文

我正在整理自己的数据库,从我见过的示例来看,外键也可以设置为主键。

我正在创建我的桌子,以便我所有的 FK 也都是 PK。这是错误的吗?什么时候FK应该成为PK?一定要PK吗?

主键在它们自己的表中有意义...作为 Id 和 Identity。但是当使用的Id是另一个表时,它也必须是PK吗?

I'm putting together my own database and from examples I've seen, Foriegn Key can also be set as Primary Keys.

I was creating my Tables so that all of my FK were also PK. Is this wrong? When should a FK be a PK? Does it have to be a PK?

Primary Key's make sense in their own table... as the Id and Identity. But when using the Id is another table, does it have to be a PK as well?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

尘曦 2024-10-15 20:11:44

当您尝试创建 1 到 11 到 0/1 映射时,外键只能作为主键。

示例:

我有一个“人员”表、一个“雇员”表和一个“承包商”表。所有员工都是人,所有承包商都是人,每个人要么是员工,要么是承包商

本质上你最终会得到这样的结果。

alt text


为了响应您的人员有多个地址,您应该创建一个关联表。这是一个图表。

alt text

正如您所看到的,现在每个人都可以有多个地址,并且由于每个员工都是一个人,因此每个员工可以有多个地址地址。对于承包商来说也是如此。


编辑:这是来自 SQL Server 的更改脚本

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Address
    (
    AddressId bigint NOT NULL,
    Address nvarchar(50) NULL,
    City nvarchar(50) NULL,
    State nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Address ADD CONSTRAINT
    PK_Address PRIMARY KEY CLUSTERED 
    (
    AddressId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Address SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Person
    (
    PersonId bigint NOT NULL,
    Name nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Person ADD CONSTRAINT
    PK_Person PRIMARY KEY CLUSTERED 
    (
    PersonId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Person SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.PersonAddress
    (
    PersonId bigint NOT NULL,
    AddressId bigint NOT NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
    PK_PersonAddress PRIMARY KEY CLUSTERED 
    (
    PersonId,
    AddressId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
    FK_PersonAddress_Person FOREIGN KEY
    (
    PersonId
    ) REFERENCES dbo.Person
    (
    PersonId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
    FK_PersonAddress_Address FOREIGN KEY
    (
    AddressId
    ) REFERENCES dbo.Address
    (
    AddressId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.PersonAddress SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Employee
    (
    EmployeeId bigint NOT NULL,
    EmployeeNumber nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT
    PK_Employee PRIMARY KEY CLUSTERED 
    (
    EmployeeId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Employee ADD CONSTRAINT
    FK_Employee_Person FOREIGN KEY
    (
    EmployeeId
    ) REFERENCES dbo.Person
    (
    PersonId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.Employee SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Contractor
    (
    ContractorId bigint NOT NULL,
    ContractorNumber nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Contractor ADD CONSTRAINT
    PK_Contractor PRIMARY KEY CLUSTERED 
    (
    ContractorId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Contractor ADD CONSTRAINT
    FK_Contractor_Person FOREIGN KEY
    (
    ContractorId
    ) REFERENCES dbo.Person
    (
    PersonId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.Contractor SET (LOCK_ESCALATION = TABLE)
GO
COMMIT

A Foreign Key should only be the Primary Key when your trying to create a 1 to 1 or 1 to zero/1 mapping.

Example:

I have a Person table, an Employee table, and a Contractor table. All Employees are people, all Contractors are people and every Person is either an employee or a Contractor

Essentially you would end up with something like this.

alt text


In response to your people have multiple addresses you should create an association table. Here is a diagram.

alt text

As you can see now every person can have many addresses and since each Employee is a person then every Employee can have many addresses. This is the same for Contractor as well.


Edited: Here is the Change Script from SQL Server

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Address
    (
    AddressId bigint NOT NULL,
    Address nvarchar(50) NULL,
    City nvarchar(50) NULL,
    State nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Address ADD CONSTRAINT
    PK_Address PRIMARY KEY CLUSTERED 
    (
    AddressId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Address SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Person
    (
    PersonId bigint NOT NULL,
    Name nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Person ADD CONSTRAINT
    PK_Person PRIMARY KEY CLUSTERED 
    (
    PersonId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Person SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.PersonAddress
    (
    PersonId bigint NOT NULL,
    AddressId bigint NOT NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
    PK_PersonAddress PRIMARY KEY CLUSTERED 
    (
    PersonId,
    AddressId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
    FK_PersonAddress_Person FOREIGN KEY
    (
    PersonId
    ) REFERENCES dbo.Person
    (
    PersonId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.PersonAddress ADD CONSTRAINT
    FK_PersonAddress_Address FOREIGN KEY
    (
    AddressId
    ) REFERENCES dbo.Address
    (
    AddressId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.PersonAddress SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Employee
    (
    EmployeeId bigint NOT NULL,
    EmployeeNumber nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT
    PK_Employee PRIMARY KEY CLUSTERED 
    (
    EmployeeId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Employee ADD CONSTRAINT
    FK_Employee_Person FOREIGN KEY
    (
    EmployeeId
    ) REFERENCES dbo.Person
    (
    PersonId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.Employee SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Contractor
    (
    ContractorId bigint NOT NULL,
    ContractorNumber nvarchar(50) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Contractor ADD CONSTRAINT
    PK_Contractor PRIMARY KEY CLUSTERED 
    (
    ContractorId
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.Contractor ADD CONSTRAINT
    FK_Contractor_Person FOREIGN KEY
    (
    ContractorId
    ) REFERENCES dbo.Person
    (
    PersonId
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.Contractor SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
格子衫的從容 2024-10-15 20:11:44

只有一种情况需要 FK 兼 PK。

当该表表示 PK 表中事物的子类或子集时,例如,SalariedEmployees 表具有与Employees 表的FK...

There is only one scenarios that would require a FK to also be a PK.

When the table represents a subclass, or subset, of the things in the PK table, for example, Eg, SalariedEmployees table which has a FK to the Employees table...

你列表最软的妹 2024-10-15 20:11:44

FK是指向另一个表的PK的字段。就是这样。
链接到自身的表可以包含指向其自身 PK 的 FK。
PK 兼 FK 只能发生在 1 对 1 关系的子表中。

A FK is a field pointing to the PK of another table. That's it.
A table linked to itself could contain a FK pointing to its own PK.
A PK that is also a FK can only happen in the child table of a 1 to 1 relationship.

残疾 2024-10-15 20:11:44

仅当两个表具有一对一关系并且添加第二个表是因为第一个表太宽且大多数查询中并不总是需要这些项目时,FK 才应该是 PK。

如果你有一对多关系或多对多关系,它根本不起作用。

FK 通常不是 PK。如果我有一个人员表和一个相关的地址表,如果我将 PK 和 FK 设置为同一对象,那么我只能存储一个地址,但大多数地址表允许同一个人或组织存储多个地址。在这种情况下,您将使用 AddressID 作为 PK,并使用 person_id 作为 person 表的 FK。这是最常见的 PK/FK 场景。

An FK should only also be a PK if the two tables have a one-to-one relationship and the second table was added because the first was too wide and these were items not always needed in most queries.

It will not work at all if you have a one-to-many relationship or a many-to-many relationship.

FKs are much more often not also the PK. If I havea person table and a related address table, If I make the PK and the FK the same thing, then I can only store one address, but most address tables allow for mulitple addresses for the same person or organization. IN that case you would have and AddressID as the PK and a person_id as the FK to the person table. This is the most common PK/FK scenario.

余罪 2024-10-15 20:11:44

给定列既是 PK 又是 FK 的一种情况是 gen-spec 设计模式的关系模型。在其他响应之一中,“Employees”是“Persons”的特化。employees 表中的 PK 引用 Persons 表中的 PK。因此,专用表中的 PK 也是一个 FK。

这允许创建一个视图将员工和个人结合起来,在一个视图中提供有关员工的所有数据,无论该数据是员工特有的(如“雇用日期”)还是所有人共有的,无论他们是否是员工(如“出生日期”) )

使每个 PK 也成为 FK 并不是一个好的做法。如果逻辑模型不合逻辑,那么您就会遇到麻烦。

One situation where a given column is both a PK and an FK is the relational model for the gen-spec design pattern. In one of the other responses "Employees" is a specialization of Persons". The PK in the employees tables references the PK in the Persons table. So the PK in the specialized table is also an FK.

This allows the creation of a view that joins employees and persons to provide in a single view all the data about employees, whether that data is peculiar to employees (like "Hire Date") or is common to all persons, whether or not they are employees (like "Date of Birth").

It is not good practice to make every PK also be an FK. The FKs should reflect the logical structure of the data. If the logical model is illogical, you're headed for trouble.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文