介绍
在设计 SQL 数据库时,可能会出现希望对可以添加到表中某些列的数据进行限制的情况。SQL 通过使用约束使这成为可能。对列或表应用约束后,任何向列或表添加不符合约束的数据的尝试都将失败。
不同的 SQL 实现有自己独特的处理约束的方式。本指南概述了许多数据库管理系统用于管理约束的语法,在整个示例中都使用 MySQL。
先决条件
为了遵循本指南,您需要一台运行某种类型的使用 SQL 的关系数据库管理系统 (RDBMS) 的计算机。本指南中的说明和示例已使用以下环境进行验证:
- 运行 Ubuntu 20.04 的服务器,具有管理权限的非 root 用户和使用 UFW 配置的防火墙,如我们的 Ubuntu 20.04 初始服务器设置指南中所述。
- 在服务器上安装并保护 MySQL,如如何在 Ubuntu 20.04 上安装 MySQL 中所述。本指南已使用新创建的用户进行验证,如步骤 3 中所述。
注意:请注意,许多 RDBMS 使用自己独特的 SQL 实现。尽管本教程中概述的命令适用于大多数 RDBMS,但如果您在 MySQL 以外的系统上测试它们,则确切的语法或输出可能会有所不同。
对 SQL 约束是什么以及它们如何起作用有一个大致的了解也将很有帮助。有关此概念的概述,您可以参考我们关于了解 SQL 约束的文章。
您还需要一个可用于练习创建带有约束的表的数据库。如果您没有这样的测试数据库,请参阅以下连接到 MySQL 和设置示例数据库部分,以了解有关如何创建数据库的详细信息。
连接和设置示例数据库
如果您的 SQL 数据库系统在远程服务器上运行,请从本地计算机通过 SSH 连接到您的服务器:
- ssh sammy@your_server_ip
然后打开 MySQL 服务器提示,替换sammy
为您的 MySQL 用户帐户的名称:
- mysql -u sammy -p
创建一个名为 的数据库constraintsDB
:
- CREATE DATABASE constraintsDB;
如果数据库创建成功,您将收到如下输出:
OutputQuery OK, 1 row affected (0.01 sec)
要选择constraintsDB
数据库,请运行以下USE
语句:
- USE constraintsDB;
OutputDatabase changed
这样,您就可以按照指南的其余部分并开始学习如何在 SQL 中创建和管理约束。
创建带有约束的表
通常,您在创建表期间定义约束。下面的 CREATE TABLE
语法创建一个名为表employeeInfo
有三列:empId
,empName
,和empPhoneNum
。该语句还UNIQUE
对该empId
列应用了约束。这将防止表中的任何行在此列中必须具有相同的值:
- CREATE TABLE employeeInfo (
- empId int UNIQUE,
- empName varchar(30),
- empPhoneNum int
- );
该语句UNIQUE
紧跟在该empId
列之后定义约束,这意味着该约束仅适用于该列。如果您尝试向该表添加任何数据,DBMS 将仅检查 的现有内容,empId
以确保您添加的任何新值empId
实际上都是唯一的。这就是所谓的列级约束。
您还可以在列定义之外应用约束。下面的示例创建一个名为表racersInfo
有三列:racerId
,racerName
,和finish
。在列定义下方,它还CHECK
对finish
列应用了约束,以确保每个赛车手的成绩都大于或等于1
(因为没有赛车手可以低于第一名):
- CREATE TABLE racersInfo (
- racerId int,
- finish int,
- racerName varchar(30),
- CHECK (finish > 0)
- );
由于约束应用于任何单个列定义之外,因此您需要在括号中指定要应用约束的列的名称。任何时候在单个列的定义之外指定约束,它都称为表级约束。列级约束仅适用于单个列,但像这样的表约束可以应用于或引用多个列。
命名约束
无论何时定义约束,您的 RDBMS 都会自动为其生成一个名称。此名称用于在用于管理约束的命令中引用错误消息中的约束。
但是,有时数据库管理员可以方便地为约束提供他们自己的名称。自动生成的约束名称通常不是描述性的,因此您自己提供一个名称可以帮助您记住约束的目的。
要命名约束,请在约束类型之前使用CONSTRAINT
关键字,后跟您选择的名称。此示例语句重新创建racersInfo
表,将其重命名为newRacersInfo
并添加noNegativeFinish
为CHECK
约束的名称:
- CREATE TABLE newRacersInfo (
- racerId int,
- finish int,
- racerName varchar(30),
- CONSTRAINT noNegativeFinish
- CHECK (finish >= 1)
- );
注意:如果您没有为约束设置名称,或者您设置了但后来忘记了它,您可能可以通过查阅数据库管理系统的信息模式来找到该名称。许多现代数据库系统和客户端甚至提供了显示CREATE
指示约束名称的内部语句的快捷方式。
以下是 MySQL 和 PostgreSQL 相关快捷方式的官方文档链接:
- MySQL:MySQL 包含
SHOW CREATE TABLE
语句,它返回CREATE TABLE
创建命名表的整个语句:
- SHOW CREATE TABLE table_name;
- PostgreSQL:PostgreSQL 客户端
psql
有许多选项可用于显示有关给定表的信息。该\d
选项返回命名表的元数据:
- \d table_name
管理约束
在 MySQL 中,您可以向现有表添加约束,也可以使用ALTER TABLE
语句删除它们。
例如,以下命令UNIQUE
向先前创建empName
的employeeInfo
表中的列添加约束:
- ALTER TABLE employeeInfo ADD UNIQUE (empName);
向现有表添加约束时,还可以使用CONSTRAINT
关键字提供名称来标识约束。此示例向先前创建的表中的列添加了一个UNIQUE
名为的约束:uID
racerId
racersInfo
- ALTER TABLE racersInfo ADD CONSTRAINT uID UNIQUE (racerId);
如果在添加这样的约束之前,您插入了任何违反新约束条件的记录,则该ALTER TABLE
语句将失败。
要删除约束,请使用DROP CONSTRAINT
语法,后跟要删除的约束的名称。此命令删除racersPK
在上一个命令中创建的约束:
- ALTER TABLE racersInfo DROP CONSTRAINT uID;
结论
通过阅读本指南,您了解了如何使用 SQL 向列和表添加和删除约束。虽然此处显示的命令应该适用于大多数关系数据库,但请注意,每个 SQL 数据库都使用自己独特的语言实现。您应该查阅 DBMS 的官方文档,以获得对每个命令及其全套选项的更完整描述。
如果您想了解有关使用 SQL 的更多信息,我们鼓励您查看本系列中关于如何使用 SQL的其他教程。