mysql 表的约束

mysql 表的约束

  • [1. 空属性](#1. 空属性)
  • [2. 默认值](#2. 默认值)
  • [3. 列描述](#3. 列描述)
  • [4. zerofill](#4. zerofill)
  • [5. 主键](#5. 主键)
  • [6. 自增长](#6. 自增长)
  • [7. 唯一键](#7. 唯一键)
  • [8. 外键](#8. 外键)

1. 空属性

在数据库中,每个字段都有一个空属性,可以是 NULL (默认)或 NOT NULL(不为空)。一般来说,应尽可能保证字段不为空,因为空值在实际运算中可能会导致问题。

示例:创建一个班级表,其中班级名称不能为空,而教室名称也不能为空。

c 复制代码
CREATE TABLE myclass (
    class_name VARCHAR(20) NOT NULL,
    classroom VARCHAR(10) NOT NULL
);

插入示例:

INSERT INTO myclass (class_name, classroom) VALUES ('班级A', '教室101');

错误的插入示例:

c 复制代码
-- 会导致错误,因为 class_name 不能为空
INSERT INTO myclass (classroom) VALUES ('教室101');

-- 会导致错误,因为 classroom 不能为空
INSERT INTO myclass (class_name) VALUES ('班级A');

2. 默认值

某些字段的数据经常会出现相同的默认值,可以在表的设计阶段指定默认值,从而在需要时使用该值。

示例:创建一个学生表,其中年龄默认为 0,性别默认为男性。

c 复制代码
CREATE TABLE students (
    name VARCHAR(50) NOT NULL,
    age TINYINT UNSIGNED DEFAULT 0,
    sex CHAR(2) DEFAULT '男'
);

插入示例:

INSERT INTO students (name) VALUES ('李四');

插入数据后:

c 复制代码
+------+-----+------+
| name | age | sex  |
+------+-----+------+
| 李四 |   0 | 男   |
+------+-----+------+

3. 列描述

列描述提供了一个字段的描述信息,虽然在数据库操作中没有实际意义,但可以帮助程序员和数据库管理员理解字段的含义。

示例:在表创建语句中添加字段描述信息。

c 复制代码
CREATE TABLE students (
    name VARCHAR(50) NOT NULL COMMENT '学生姓名',
    age TINYINT UNSIGNED DEFAULT 0 COMMENT '学生年龄',
    sex CHAR(2) DEFAULT '男' COMMENT '学生性别'
);

查询表的注释内容,我们可以使用SHOW CREATE TABLE命令:

SHOW CREATE TABLE students\G;

4. zerofill

在数据库中,对于数字类型的字段,有时候需要对其进行填充以保持一致的显示格式。这时就可以使用 zerofill 属性来实现。

int 类型字段后面的长度常常让人迷惑,如 int(10) 。但实际上,没有使用 zerofill 属性时,括号内的数字对数据存储并无实质影响。

让我们通过一个例子来说明 zerofill 的作用。假设我们有一个表 tt3 ,其中包含两个整型字段 ab

c 复制代码
CREATE TABLE tt3 (
    a INT(10) UNSIGNED DEFAULT NULL,
    b INT(10) UNSIGNED DEFAULT NULL
) ENGINE=MYISAM DEFAULT CHARSET=gbk;

现在,我们向表中插入数据:

INSERT INTO tt3 VALUES (1, 2);

如果我们查询表 tt3,将得到如下结果:

c 复制代码
+------+------+
| a    | b    |
+------+------+
| 1    | 2    |
+------+------+

现在,让我们给字段 a 添加 zerofill 属性,并将宽度设为 5

ALTER TABLE tt3 CHANGE a a INT(5) UNSIGNED ZEROFILL;

再次查看表的创建语句,可以看到 a 字段现在具有了 zerofill 属性:

c 复制代码
CREATE TABLE tt3 (
    a INT(5) UNSIGNED ZEROFILL DEFAULT NULL,
    b INT(10) UNSIGNED DEFAULT NULL
) ENGINE=MYISAM DEFAULT CHARSET=gbk;

现在,如果我们再次查询表 tt3,将得到如下结果:

c 复制代码
+-------+------+
| a     | b    |
+-------+------+
| 00001 | 2    |
+-------+------+

可以看到,字段 a 的值现在以 5 位宽度进行显示,并在不足位数时自动填充 0 。但需要注意的是,这只是最后的显示结果,在 MySQL 中实际存储的仍然是整数值 1 。可以通过使用 hex 函数查看内部存储值:
SELECT a, HEX(a) FROM tt3;

5. 主键

主键(Primary Key)是数据库中一种重要的约束,用于唯一标识表中的每一行数据。主键字段的值不能重复,也不能为空。在一张表中,最多只能有一个主键。

通常情况下,主键所在的列是整数类型,但也可以是其他类型,只要保证能够唯一标识每一行数据即可。

创建表时指定主键

在创建表的时候,可以直接在字段定义时指定主键。

c 复制代码
CREATE TABLE students (
    id INT UNSIGNED PRIMARY KEY COMMENT '学号不能为空',
    name VARCHAR(20) NOT NULL
);

在上面的示例中,id 字段被指定为主键,其类型为无符号整数,同时也是不能为空的。

主键约束 保证了主键字段中的数值是唯一的,任何试图插入重复值的操作都会失败。

c 复制代码
INSERT INTO students VALUES(1, 'John');
若再次尝试插入相同的主键值,将会收到错误提示:
c 复制代码
INSERT INTO students VALUES(1, 'John');
-- ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

添加和删除主键

在表创建完成后,如果没有指定主键,可以通过 ALTER TABLE 语句追加主键或删除主键。

添加主键:

ALTER TABLE students ADD PRIMARY KEY(id);

删除主键:

ALTER TABLE students DROP PRIMARY KEY;

复合主键

除了单一字段外,还可以使用多个字段组合成复合主键。

c 复制代码
CREATE TABLE exam_scores (
    student_id INT UNSIGNED,
    course_code CHAR(10) COMMENT '课程代码',
    score TINYINT UNSIGNED DEFAULT 60 COMMENT '成绩',
    PRIMARY KEY(student_id, course_code)
);

在上面的示例中,student_id 和 course_code 组合成了复合主键,保证了每一行数据的唯一性。

c 复制代码
INSERT INTO exam_scores (student_id, course_code) VALUES(1, 'Math');
INSERT INTO exam_scores (student_id, course_code) VALUES(1, 'Math');
-- ERROR 1062 (23000): Duplicate entry '1-Math' for key 'PRIMARY'

通过以上示例,我们了解了主键在数据库中的重要性以及如何使用主键来确保数据的唯一性和完整性。

6. 自增长

自增长(Auto Increment)是一种数据库中常见的特性,用于自动分配唯一的递增值给指定的字段,通常与主键一起使用。

自增长的特点包括:

任何一个字段要做自增长,前提是本身是一个索引(即有值)

自增长字段必须是整数类型

一张表最多只能有一个自增长字段

案例:使用自增长字段

在创建表时,可以使用 AUTO_INCREMENT 属性来实现自增长:

c 复制代码
CREATE TABLE students (
    id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(10) NOT NULL DEFAULT ''
);

在上面的示例中,id 字段被指定为主键,并设置为自增长。当插入数据时,如果不给 id 字段赋值,系统会自动为其分配一个唯一的递增值。

-- 插入数据,自增长字段 id 会自动分配
INSERT INTO students(name) VALUES('John');
INSERT INTO students(name) VALUES('Alice');
INSERT INTO students(name) VALUES(100,'Bob');
INSERT INTO students(name) VALUES('Carol');
INSERT INTO students(name) VALUES('David');

以上操作将在 students 表中插入两行数据,每行数据的 id 字段会自动递增,生成唯一的值。

插入两行数据后,表中的数据可能如下所示:

c 复制代码
+------+-------+
| id   | name  |
+------+-------+
|  1   | John  |
|  2   | Alice |
|  100 | Bob   |
|  101 | Carol |
|  102 | David |
+-----+--------+

在创建表时指定自动增长的初始值:

c 复制代码
CREATE TABLE customers (
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    tel VARCHAR(11),
    sex VARCHAR(1)
) AUTO_INCREMENT=1000;

或者创建后修改自动增长的初始值:

ALTER TABLE customers AUTO_INCREMENT=1000;

自增长的注意事项

一个表中只能有一个字段使用AUTO_INCREMENT 约束,且该字段必须有唯一索引,通常为主键或主键的一部分。

自增长字段必须具备NOT NULL 属性。

自增长字段只能是整数类型,例如TINYINT、SMALLINT、INT、BIGINT 等。

自增长字段的最大值受该字段的数据类型约束,如果达到上限,自增长机制就会失效。

7. 唯一键

MySQL中,一张表往往有多个字段需要保证唯一性,即数据不能重复。然而,每张表只能有一个主键,这时就需要使用唯键来解决这个问题。唯键类似于主键,但有一些区别:

允许为空:唯键允许字段为空,且可以有多个空值,空字段不会进行唯一性比较。

多个字段约束:唯键可以约束表中的多个字段,保证组合后的数据在业务上不重复。

主键与唯键的区别

主键更多地用于标识唯一性,而唯键则更多地用于保证业务上的数据不重复。举个例子来说:

假设我们有一个商品管理系统,商品表中有商品编号和商品条形码两列信息。我们可以将商品编号作为主键,因为它可以唯一标识一个商品。而商品条形码需要保证在公司的业务上不能重复,但并不一定唯一标识一个商品,因此可以设计成唯一键。

以下是如何使用主键和唯键设计产品表的示例:

c 复制代码
CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    Barcode VARCHAR(20) UNIQUE,
    ProductName VARCHAR(50),
    QuantityInStock INT
);

在这个示例中,ProductID 被设置为主键,因为它唯一标识每个产品。同时,Barcode 被设计为唯键,以确保每个产品都有一个唯一的条形码。

INSERT INTO Products VALUES(1, 'ABC123', 'Product A', 100);
INSERT INTO Products VALUES(2, 'XYZ789', 'Product B', 50);
INSERT INTO Products VALUES(3, 'ABC123', 'Product C', 75);--唯键约束不允许重复的条形码

删除唯一键:
DROP INDEX 唯一键名 ON 表名;

添加唯一键:
ALTER TABLE 表名 ADD CONSTRAINT 唯一键名 UNIQUE (列名);

8. 外键

在数据库设计中,表与表之间的关联关系是非常常见的。外键约束(Foreign Key Constraint)就是用来定义表与表之间的关联关系的一种重要约束,它确保了数据的完整性和一致性。

什么是外键?

外键是一种表的字段,它指向另一个表中的主键或唯一键,从而建立了两个表之间的关系。通常,外键约束主要定义在从表上,从表中的外键列的数据必须在主表的主键列或唯一键列中存在,或者允许为空。

外键的语法

c 复制代码
CREATE TABLE 表名 (
    列名 数据类型,
    FOREIGN KEY (外键列名) REFERENCES 主表名(主键列名)
);

示例:学生表与班级表的关联

假设我们有一个学生管理系统,其中包含学生表(students )和班级表(classes)。学生属于某个班级,我们需要通过外键约束来确保学生所属的班级在班级表中存在。

首先,我们创建班级表:

c 复制代码
CREATE TABLE classes (
    class_id INT PRIMARY KEY,
    class_name VARCHAR(50) NOT NULL
);

接下来,创建学生表,并添加外键约束:

c 复制代码
CREATE TABLE students (
    student_id INT PRIMARY KEY,
    student_name VARCHAR(50) NOT NULL,
    class_id INT,
    FOREIGN KEY (class_id) REFERENCES classes(class_id)
);

示例:插入数据

c 复制代码
-- 插入班级数据
INSERT INTO classes VALUES (1, 'C++班'), (2, 'Java班');

-- 插入学生数据,包括存在的班级和不存在的班级
INSERT INTO students VALUES (101, '张三', 1), (102, '李四', 2), (103, '王五', 3);

上述插入数据的最后一条语句会报错,因为学生表中的班级编号 3 在班级表中不存在。

相关推荐
m0_748248021 小时前
Redis 简介与安装指南
数据库·redis·缓存
Elastic 中国社区官方博客6 小时前
在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
编程爱好者熊浪7 小时前
两次连接池泄露的BUG
java·数据库
南宫乘风9 小时前
基于 Flask + APScheduler + MySQL 的自动报表系统设计
python·mysql·flask
TDengine (老段)9 小时前
TDengine 字符串函数 CHAR 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
qq7422349849 小时前
Python操作数据库之pyodbc
开发语言·数据库·python
姚远Oracle ACE10 小时前
Oracle 如何计算 AWR 报告中的 Sessions 数量
数据库·oracle
Dxy123931021610 小时前
MySQL的SUBSTRING函数详解与应用
数据库·mysql
码力引擎10 小时前
【零基础学MySQL】第十二章:DCL详解
数据库·mysql·1024程序员节
杨云龙UP10 小时前
【MySQL迁移】MySQL数据库迁移实战(利用mysqldump从Windows 5.7迁至Linux 8.0)
linux·运维·数据库·mysql·mssql