Skip to content

SQL Constraints

SQL 约束(constraints)是对表内数据列强制执行的规则。它们用于确保数据的准确性、可靠性和完整性(integrity)。如果任何 DML 操作(INSERT、UPDATE、DELETE)违反了约束,则操作将被中止。

约束可以在两个级别定义:

  • **列级(Column-level):**作为列定义的一部分进行定义,仅适用于该特定列。
  • **表级(Table-level):**与列定义分开定义,可以应用于表中的一列或多列(对于多列主键或唯一约束是必需的)。

约束可以在使用 CREATE TABLE 创建表时指定,也可以使用 ALTER TABLE 添加到现有表中。

以下是最常用的 SQL 约束:

  1. **NOT NULL**

    确保列不能包含 NULL 值。每一行都必须为该列提供一个值。

    -- 列级约束
    

CREATE TABLE Employees ( EmployeeID INT NOT NULL, LastName VARCHAR(255) NOT NULL, FirstName VARCHAR(255) ); 2.

  • UNIQUE

    确保列(或一组列)中的所有值都是唯一的。一个表可以有多个 UNIQUE 约束。通常允许 NULL 值(并且通常允许多个 NULL 值,因为 NULL 不等于 NULL,但具体行为可能因 RDBMS 而异)。

    — 列级约束
    CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductCode VARCHAR(50) UNIQUE,
    ProductName VARCHAR(255)
    );
    — 表级约束 (用于多列唯一约束)
    CREATE TABLE UserSettings (
    UserID INT,
    SettingKey VARCHAR(100),
    SettingValue VARCHAR(255),
    CONSTRAINT UQ_UserSetting UNIQUE (UserID, SettingKey)
    );
  • 3.
  • PRIMARY KEY

    唯一标识表中的每一条记录。主键必须包含唯一值且不能包含 NULL 值(它隐式地是 NOT NULL 和 UNIQUE)。一个表只能有一个主键,主键可以由单列或多列组成(复合键)。

    — 列级约束
    CREATE TABLE Departments (
    DepartmentID INT PRIMARY KEY,
    DepartmentName VARCHAR(100)
    );
    — 表级约束 (用于复合主键)
    CREATE TABLE OrderDetails (
    OrderID INT,
    ProductID INT,
    Quantity INT,
    PRIMARY KEY (OrderID, ProductID)
    );
  • 4.
  • FOREIGN KEY

    通过将一个表中的列(或多列)链接到另一个表(父表)中的主键或唯一键来确保参照完整性(referential integrity)。这可以防止导致孤立记录的操作。您还可以指定操作,例如 ON DELETE CASCADE(当父行被删除时删除子行)或 ON UPDATE SET NULL(如果父键被更新,则将外键设置为 NULL)。

    CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerID INT,
    OrderDate DATE,
    CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerID)
    REFERENCES Customers(CustomerID)
    ON DELETE SET NULL — 示例操作
    );
    — (假设存在一个 Customers 表,其 CustomerID 是 PRIMARY KEY)
  • 5.
  • CHECK

    确保列中的所有值满足特定的条件或表达式。条件必须评估为 TRUE 或 UNKNOWN(例如,当检查 NULL 值时)才能满足约束。

    CREATE TABLE Employees (
    EmployeeID INT PRIMARY KEY,
    Salary DECIMAL(10, 2),
    Age INT,
    CONSTRAINT CK_Salary CHECK (Salary > 0),
    CONSTRAINT CK_Age CHECK (Age >= 18 AND Age <= 65)
    );
  • 6.
  • DEFAULT

    当在 INSERT 操作期间没有为列显式提供值时,为该列指定一个默认值。

    CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductName VARCHAR(255) NOT NULL,
    StockQuantity INT DEFAULT 0,
    DateAdded TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
  • 在创建表时 (CREATE TABLE):

    CREATE TABLE table_name ( column1 datatype [CONSTRAINT constraint_name] column_constraint, column2 datatype [DEFAULT default_value], … [CONSTRAINT table_constraint_name] table_constraint (column_list) );

    向现有表添加约束 (ALTER TABLE):

    ALTER TABLE table_name ADD CONSTRAINT constraint_name constraint_type (column_list);

    示例:ALTER TABLE Employees ADD CONSTRAINT CK_EmpEmail CHECK (Email LIKE '%@%.%');

    命名约束(例如 FK_CustomerOrder、CK_Salary)是一个好习惯,因为它使它们更容易管理(例如,以后删除或修改)并更容易从错误消息中理解。

    • **数据完整性:**防止无效或不一致的数据被输入到数据库中。
    • **数据准确性:**有助于维护数据的正确性。
    • **数据库结构:**定义表之间的关系并在数据库级别强制执行业务规则。
    • **性能:**主键和唯一约束通常有相关的索引,这可以提高查询速度。

    接下来的章节将更详细地描述其中一些约束,重点介绍它们的应用方式及其影响。