SQL完整性约束

完整性约束

DBMS为了保证存储的数据都是完整有效的,避免存放垃圾数据,所以提供针对插入的数据进行检查。

  • 开发人员指定对应的规则,由DBMS负责检查,如果试图插入不合法的数据,则会自动报错,拒绝插入
  • 实际有6种约束,可以分为3大类完整性约束。有些老外的书种提出的是4种【域完整性】
  1. 实体完整性,由主键约束实现
  2. 参照完整性,由外键约束实现
  3. 用户自定义完整性,由其他4种约束实现
  • 实际开发中除了主键约束外,其它约束一概不添加。其他的数据检查一般依赖应用程序实现,为了代码测试方便

1、非空约束,指定列值不允许为空

create table t1(id int not null); --不允许id列值为null
create table t2(id int null); -- 允许id列值为null
create table 3(id int);-- 允许id列值为null

 插入null值有2种情况:直接插入null,或者没有在表上定义default而不插入数据,则默认null

2、默认约束default

一般默认约束经常和非空约束一起使用,当不插入数据时,默认值生效

create table t1(id int not null default 0); -- not null不是必须的
create table t2(id datetime default now()); -- 正确的,过去只有timestamp default
current_timestamp

 3、主键约束,又叫做实体完整性,不允许数据重复存储

  • 主键可以唯一标识一行数据,一个表中只能有一个主键,但是主键允许是由多个列构成
  • 主键约束含义是非空、唯一
create table t1(id int primary key,....); -- 单一主键,
create table t2(
id int not null,...
primary key(id) -- 注意这里的主键约束允许使用复合主键,多个列构成的主键
);
复合主键中的任一列即使没有添加not null约束,也不允许为null

使用InnoDB存储引擎时,如果数据表没有设置主键,那么Innodb会给该表设置一个不可见,长度为6字 节的默认主键 row_id。Innodb维护了一个全局的dict_sys.row_id值,这个值,被所有无主键的数据表 共同使用,每个无主键的数据表,插入一行数据,都会是当前的dict_sys.row_id的值增加1

实row_id的值在存储时,数据长度为8字节,只不过Innodb只使用后6个字节。那么row_id的值,写到 数据表中时就有一下两个特点:

1.row_id写入表中的值范围,是从0-2^48-1。

2.当row_id的值为2^48时,再进行数据插入,那么row_id的后6个字节的值,就全部为0了。

也就是说,当row_id的值到了2^48次方-1后,再次插入数据,下一个值就是0,然后开始循环。不过和 自定义主键不同的是,row_id标识的主键,没有唯一性约束,当插入数据的row_id值,在表中已经存在 的话,那么写入的数据会"悄无声息"覆盖已存在的数据。

表尽可能都要设置主键,主键尽量使用bigint类型,21亿的上限还是有可能达到的,比如魔兽,虽然说 row_id上限高达281万亿,但是覆盖数据显然是不可接受的。 根据主键是否有业务含义可以分为业务主键和代理主键 

4、唯一约束 unique

不允许添加唯一性约束的列出现重复值

可以没有null值约束,而且也不能针对null进行唯一性判定 

create table t1(id int unique,name varchar(20));
insert into t1 values(1,'zhangsan');
insert into t1(name) values('zhao4');-- id为null
insert into t1(name) values('zhao4');-- id为null,两次null并不会报错
insert into t1 values(1,'li4'); -- 报错
mysql> create table t23(
-> id int,
-> name varchar(32),
-> unique(id,name)); -- 多个列的组合不允许重复,单一列允许重复

5、外键约束,又叫做参照完整性

6、检查约束check

mysql> create table t24(
-> id boolean default 1,
-> check(id in(1,0)));

 

<think>好的,用户现在想了解SQL完整性约束。之前他们已经问过多表联合查询,现在转向数据库的另一个重要概念,说明他们可能在深入学习数据库设计或优化方面的内容。首先,我需要回顾一下完整性约束的基本定义和类型,确保覆盖主要的关键点。 用户可能对完整性约束不太熟悉,所以需要从基础讲起,比如实体完整性、参照完整性、域完整性等。同时,要结合实际应用场景,这样用户更容易理解这些约束的作用。比如,实体完整性通过主键实现,确保每行数据唯一;参照完整性通过外键维护表之间的关系,防止出现无效的引用。 然后,要考虑用户可能的疑问,比如不同的约束类型如何在SQL中具体实现,可能需要示例代码。例如,创建表时如何定义主键、外键、检查约束等。还要注意用户是否了解这些约束数据库设计中的重要性,比如保证数据的一致性和准确性。 用户可能还会关心约束的命名和修改,比如如何添加或删除约束,这也是实际应用中常见的操作。需要提供相应的SQL语法示例,比如使用ALTER TABLE来添加外键约束。此外,触发器和断言虽然不常用,但作为高级内容可以简要提及,让用户有全面的了解。 还需要注意用户可能混淆的概念,比如唯一约束和主键的区别,或者检查约束与触发器的适用场景。这时候需要明确解释它们的异同,帮助用户正确选择使用哪种约束方式。 另外,考虑用户的实际操作,可能需要提醒一些注意事项,比如外键约束可能带来的性能影响,或者在插入大量数据时暂时禁用约束以提高效率。这些实战技巧对用户来说应该很有帮助。 最后,总结完整性约束的重要性,并给出学习建议,比如通过实际创建表并测试约束来加深理解。可能推荐一些在线工具或练习平台,方便用户动手实践。</think>以下是关于 **SQL完整性约束** 的详细介绍,涵盖核心概念、分类及实际应用: --- ### **一、完整性约束的核心作用** 保证数据库中数据的 **准确性**、**一致性** 和 **可靠性**,防止无效或矛盾数据进入数据库。 **类比**:类似于交通规则,约束数据的“行为规范”。 --- ### **二、约束类型与语法详解** #### **1. 实体完整性(Entity Integrity)** - **目标**:确保表中每行数据的唯一性 - **实现方式**:主键(`PRIMARY KEY`) ```sql CREATE TABLE Students ( student_id INT PRIMARY KEY, -- 列级约束 name VARCHAR(50) ); -- 或表级约束(联合主键) CREATE TABLE Enrollments ( student_id INT, course_id INT, PRIMARY KEY (student_id, course_id) ); ``` #### **2. 参照完整性(Referential Integrity)** - **目标**:维护表间关系的一致性 - **实现方式**:外键(`FOREIGN KEY`) ```sql CREATE TABLE Orders ( order_id INT PRIMARY KEY, customer_id INT, FOREIGN KEY (customer_id) REFERENCES Customers(customer_id) ON DELETE CASCADE -- 级联删除 ); ``` #### **3. 域完整性(Domain Integrity)** - **目标**:限定字段的取值范围 - **实现方式**: - **非空约束**:`NOT NULL` ```sql CREATE TABLE Users ( username VARCHAR(20) NOT NULL ); ``` - **唯一约束**:`UNIQUE` ```sql CREATE TABLE Products ( product_code VARCHAR(10) UNIQUE ); ``` - **检查约束**:`CHECK` ```sql CREATE TABLE Employees ( age INT CHECK (age >= 18), gender CHAR(1) CHECK (gender IN ('M', 'F')) ); ``` #### **4. 用户定义完整性(自定义规则)** - **实现方式**:触发器(`TRIGGER`)或存储过程 ```sql CREATE TRIGGER salary_check BEFORE INSERT ON Employees FOR EACH ROW BEGIN IF NEW.salary < 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '薪资不能为负数'; END IF; END; ``` --- ### **三、约束操作进阶技巧** #### **1. 约束命名与修改** ```sql -- 添加命名约束 ALTER TABLE Students ADD CONSTRAINT chk_age CHECK (age BETWEEN 12 AND 25); -- 删除约束 ALTER TABLE Students DROP CONSTRAINT chk_age; ``` #### **2. 外键约束行为控制** | **操作** | **说明** | |----------------|----------------------------------| | `ON DELETE CASCADE` | 主表记录删除时,从表关联记录同步删除 | | `ON UPDATE SET NULL` | 主表主键更新时,从表外键设为 NULL | #### **3. 延迟约束检查** (适用于 PostgreSQL/Oracle) ```sql SET CONSTRAINTS ALL DEFERRED; -- 事务提交时统一检查 ``` --- ### **四、典型应用场景** 1. **电商系统** - 使用 `CHECK(quantity > 0)` 确保库存不为负 - 外键约束保证订单关联的用户必须存在 2. **金融系统** - `NOT NULL` 强制要求交易金额字段必填 - 触发器检查转账金额不超过账户余额 3. **社交平台** - `UNIQUE(email)` 防止重复注册 - `CHECK(LENGTH(password) >= 8)` 密码强度限制 --- ### **五、注意事项与优化** | **问题** | **解决方案** | |-------------------------|----------------------------------| | 过多外键影响写入性能 | 在批量导入时临时禁用约束 | | 检查约束跨表验证困难 | 改用触发器实现复杂逻辑 | | 主键选择不当导致碎片化 | 优先使用自增整型或UUID | --- ### **六、扩展知识:断言(ASSERTION)** - **作用**:跨表的全局性约束(但 MySQL 不支持) - **示例**(SQL标准语法): ```sql CREATE ASSERTION budget_limit CHECK ( NOT EXISTS ( SELECT department_id FROM Projects GROUP BY department_id HAVING SUM(budget) > 1000000 ) ); ``` --- **学习建议**: 1. 在 MySQL Workbench 或 pgAdmin 中创建带约束的表,尝试插入违反约束的数据观察报错 2. 使用 `SHOW CREATE TABLE table_name;` 查看已有表的约束定义 3. 重点理解不同约束对数据一致性的保护机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值