数据库主键和外键

主键和外键:

从技术上来讲,主键约束只是唯一约束和非空约束的组合。

CREATE TABLE products (
product_no integer PRIMARY KEY, --字段 product_no 被定义为该表的唯一主键。
name text,
price numeric
);

和唯一性约束一样,主键可以同时作用于多个字段,形成联合主键:

CREATE TABLE example (
a integer,
b integer,
c integer,
PRIMARY KEY (b, c)
);

外键约束声明一个字段(或者一组字段)的数值必须匹配另外一个表中某些行出现的数值。 我们把这个行为称做两个相关表之间的参考完整性。

CREATE TABLE orders (
order_id integer PRIMARY KEY, --该表也可以有自己的主键。
--该表的 product_no 字段为上面 products 表主键(product_no)的外键。
product_no integer REFERENCES products(product_no),
quantity integer
);
CREATE TABLE t1 (
a integer PRIMARY KEY,
b integer,
c integer,
--该外键的字段数量和被引用表中主键的数量必须保持一致。
FOREIGN KEY (b, c) REFERENCES example (b, c)
);

当多个表之间存在了主外键的参考性约束关系时,如果想删除被应用表(主键表)中的某行记录,由于该行记录的主键字段值可能正在被其引用表(外键表)中某条记录所关联,所以删除操作将会失败。如果想完成此操作,一个显而易见的方法是先删除引用表中和该记录关联的行,之后再删除被引用表中的该行记录。然而需要说明的是,PostgreSQL 为我们提供了更为方便的方式完成此类操作。

CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
);

CREATE TABLE orders (
order_id integer PRIMARY KEY,
shipping_address text
);

CREATE TABLE order_items (
product_no integer REFERENCES products ON DELETE RESTRICT, --限制选项
order_id integer REFERENCES orders ON DELETE CASCADE, --级联删除选项
quantity integer,
PRIMARY KEY (product_no, order_id)
);

限制和级联删除是两种最常见的选项。RESTRICT 禁止删除被引用的行。 NO ACTION 的意思是如果在检查约束的时候,如果还存在任何引用行,则抛出错误; 如果你不声明任何东西,那么它就是缺省的行为。(这两个选择的实际区别是,NO ACTION 允许约束检查推迟到事务的晚些时候,而 RESTRICT 不行。) CASCADE 声明在删除一个被引用的行的时候,引用它的行也会被自动删除掉。 在外键字段上的动作还有两个选项: SET NULL 和 SET DEFAULT。这样会导致在被引用行删除的时候,引用它们的字段分别设置为空或者缺省值。 请注意这些选项并不能让你逃脱被观察和约束的境地。比如,如果一个动作声明 SET DEFAULT,但是缺省值并不能满足外键,那么动作就会失败。类似ON DELETE,还有 ON UPDATE 选项,它是在被引用字段修改(更新)的时候调用的。可用的动作是一样的。

不使用外键的理由

  1. 外键说白了就是为了维护数据强一致性的。当年的数据库在金融领域应用最多最早,所以强一致性要求很高。而现在绝大部分公司的业务,哪需要这么高的强一致性啊

  2. 基本不使用外键。外键关系使用程序代码来维护,在数据库中不体现。后期如果需要数据清理,数据调整时,有外键关系(尤其是复杂的外键关系)会造成表数据非常难以修改、维护

  3. 性能影响,分布式不考虑外键,外键本身是为了实现强一致性,跟大规模并发和分布式都是冲突的

    在不用外键的前提下,其实就是自己在代码里面通过逻辑去实现约束,在多对多的关系时可以考虑使用中间表。

### 主键的概念 在 MySQL 数据库中,主键用于唯一标识表中的每一行数据。每个表只能定义一个主键,并且主键的值不允许重复或为 `NULL`。这确保了每一条记录都具有唯一性[^2]。 则是一种约束机制,用于建立并维护两个表之间的关系。通过可以实现参照完整性,从而防止意删除或修改相关联的数据[^1]。 --- ### 主键的用法及示例 #### 创建带有主键的表 可以通过在创建表时指定某个字段为主键来实现: ```sql CREATE TABLE Users ( UserID INT PRIMARY KEY, -- 设置UserID为主键 UserName VARCHAR(50), Email VARCHAR(100) ); ``` 在这个例子中,`UserID` 字段被设定为主键,因此它的值在整个表中必须是唯一的,且不能为空[^2]。 #### 添加主键到已存在的表 如果需要向已经存在的表添加主键,可以使用如下语句: ```sql ALTER TABLE Users ADD PRIMARY KEY (UserID); -- 将UserID设为主键 ``` 注意:只有当该列不包含任何重复值或 `NULL` 值时,才能成功执行此操作[^3]。 --- ### 的用法及示例 #### 定义 假设存在两张表——`Users` `Orders`,其中 `Orders` 表中的 `UserID` 列应该引用 `Users` 表中的 `UserID` 列,则可以在创建 `Orders` 表时定义: ```sql CREATE TABLE Orders ( OrderID INT PRIMARY KEY, UserID INT, ProductName VARCHAR(100), FOREIGN KEY (UserID) REFERENCES Users(UserID) -- 定义 ); ``` 在此情况下,`Orders.UserID` 的取值范围受到限制,仅允许那些已经在 `Users.UserID` 中存在的值[^1]。 #### 删除 若需移除约束,可使用以下命令: ```sql ALTER TABLE Orders DROP FOREIGN KEY fk_UserId; -- 移除名为fk_UserId的 ``` 需要注意的是,具体名称可能因数据库设计而异,建议先查询的具体名字再进行删除操作[^3]。 --- ### 组合主键的实际应用案例 考虑学生选课系统的场景,涉及三个实体:“学生”、“课程”以及它们的关系“选课”。以下是具体的建模过程: 1. **创建 Student 表** 学生表包含学号 (`StudentNo`) 及姓名等基本信息,其中 `StudentNo` 是主键。 ```sql CREATE TABLE Student ( StudentNo CHAR(4) PRIMARY KEY, -- 学号作为主键 Name VARCHAR(50), Age INT, Dept VARCHAR(20) ); ``` 2. **创建 Course 表** 课程表包含课程编号 (`CourseNo`) 课程名等信息,同样以 `CourseNo` 作为主键。 ```sql CREATE TABLE Course ( CourseNo CHAR(4) PRIMARY KEY, -- 课程编号作为主键 CourseName VARCHAR(100) ); ``` 3. **创建 Selection 表** 这是一个中间表,表示学生与所选课程之间的关联关系。这里既设置了复合主键 `(StudentNo, CourseNo)` 来保证唯一性,又分别对进行了约束。 ```sql CREATE TABLE Selection ( StudentNo CHAR(4), CourseNo CHAR(4), Grade DECIMAL(5, 2), PRIMARY KEY (StudentNo, CourseNo), -- 联合主键 FOREIGN KEY (StudentNo) REFERENCES Student(StudentNo), -- 对应学生的 FOREIGN KEY (CourseNo) REFERENCES Course(CourseNo) -- 对应课程的 ); ``` 以上结构能够有效管理学生及其选修课程的信息,同时利用主键保障数据的一致性完整性。 --- ### 性能优化提示 虽然主键对于保持数据一致性至关重要,但在高并发写入环境中可能会带来性能开销。例如,频繁更新含有大量依赖的表可能导致锁等待时间增加。在这种情形下,可以根据实际需求权衡是否启用某些约束[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值