一、约束定义
约束是用于定义和实施表的规则和限制,以确保数据的完整性和一致性。
即对一张表中的属性操作进行限制。
二、约束分类
通过定义约束,可以对数据库中的数据进行限制,以下是常见的约束:
- 主键约束(Primary Key Constraint):
-
用途:用于唯一标识表中的每一行数据,并且不允许为空。
-
语法:`PRIMARY KEY (column1, column2, ...)`。
- 外键约束(Foreign Key Constraint):
-
用途:用于建立表与表之间的关系,确保引用其他表中存在的值。
-
语法:`FOREIGN KEY (column1, column2, ...) REFERENCES parent_table (parent_column1, parent_column2, ...)`。
- 唯一约束(Unique Constraint):
-
用途:确保表中的某个列或一组列的值是唯一的。
-
语法:`UNIQUE (column1, column2, ...)`。
- 检查约束(Check Constraint):
-
用途:定义一个布尔表达式来评估插入或更新的值是否满足特定条件。
-
语法:`CHECK (condition)`。
- 默认约束(Default Constraint):
-
用途:为给定列提供默认值,如果插入或更新操作未指定该列的值,则将使用默认值。
-
语法:`DEFAULT value`。
- 非空约束(Not Null Constraint):
-
用途:确保列不允许包含空值。
-
语法:`column_name datatype NOT NULL`。
约束可以在创建表时直接定义,也可以在后期通过修改表结构来添加或删除。使用约束可以提高数据库的完整性和一致性,防止无效或不符合规范的数据被插入到表中。
四、约束相关语法格式
使用以下语法格式来创建、删除和修改六种常见的约束类型:主键约束、唯一约束、外键约束、检查约束、默认约束和非空约束。
4.1主键约束(Primary Key Constraint):
sql
--1.创建主键约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 PRIMARY KEY (列名);
-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT PK_Employees PRIMARY KEY (EmployeeID);
--2.删除主键约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT PK_Employees;
--3.修改主键约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
ALTER TABLE 表名
ADD CONSTRAINT 新约束名 PRIMARY KEY (列名);
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT PK_Employees;
ALTER TABLE Employees
ADD CONSTRAINT PK_Employees_New PRIMARY KEY (EmployeeID);
4.2外键约束(Foreign Key Constraint):
sql
--1.创建外键约束
-- 语法格式:
ALTER TABLE 子表名
ADD CONSTRAINT 约束名
FOREIGN KEY (子表关联列)
REFERENCES 主表名 (主表关联列);
-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT FK_Employees_Departments
FOREIGN KEY (DepartmentID)
REFERENCES Departments(DepartmentID);
--2.删除外键约束
-- 语法格式:
ALTER TABLE 子表名
DROP CONSTRAINT 约束名;
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT FK_Employees_Departments;
--3.修改外键约束
-- 语法格式:
ALTER TABLE 子表名
DROP CONSTRAINT 约束名;
ALTER TABLE 子表名
ADD CONSTRAINT 新约束名 FOREIGN KEY (子表关联列)
REFERENCES 主表名 (主表关联列);
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT FK_Employees_Departments;
ALTER TABLE Employees
ADD CONSTRAINT FK_Employees_Departments_New
FOREIGN KEY (DepartmentID)
REFERENCES Departments(DepartmentID);
4.3唯一约束(Unique Constraint):
sql
--1.创建唯一约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 UNIQUE (列名);
-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT UQ_Employees_Email UNIQUE (Email);
--2.删除唯一约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT UQ_Employees_Email;
--3.修改唯一约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
ALTER TABLE 表名
ADD CONSTRAINT 新约束名 UNIQUE (列名);
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT UQ_Employees_Email;
ALTER TABLE Employees
ADD CONSTRAINT UQ_Employees_Email_New UNIQUE (Email);
4.4检查约束(Check Constraint):
sql
--1.创建检查约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 CHECK (条件);
-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT CK_Employees_Salary CHECK (Salary > 0);
--2.删除检查约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT CK_Employees_Salary;
--3.修改检查约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
ALTER TABLE 表名
ADD CONSTRAINT 新约束名 CHECK (条件);
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT CK_Employees_Salary;
ALTER TABLE Employees
ADD CONSTRAINT CK_Employees_Salary_New CHECK (Salary > 1000);
4.5默认约束(Default Constraint):
sql
--1.创建默认约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 DEFAULT 默认值 FOR 列名;
-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT DF_Employees_HireDate DEFAULT GETDATE() FOR HireDate;
--2.删除默认约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 DROP DEFAULT;
-- 示例:
ALTER TABLE Employees
ALTER COLUMN HireDate DROP DEFAULT;
--3.修改默认约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;
ALTER TABLE 表名
ADD CONSTRAINT 新约束名 DEFAULT 默认值 FOR 列名;
-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT DF_Employees_HireDate;
ALTER TABLE Employees
ADD CONSTRAINT DF_Employees_HireDate_New DEFAULT GETDATE() FOR HireDate;
4.6非空约束(Not Null Constraint):
sql
--1.创建非空约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 数据类型 NOT NULL;
-- 示例:
ALTER TABLE Employees
ALTER COLUMN Address VARCHAR(100) NOT NULL;
--2.删除非空约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 数据类型 NULL;
-- 示例:
ALTER TABLE Employees
ALTER COLUMN Address VARCHAR(100) NULL;
--3.修改非空约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 数据类型 NOT NULL;
-- 示例:
ALTER TABLE Employees
ALTER COLUMN Address VARCHAR(200) NOT NULL;
注意:
通过使用以上的语法格式,可以对指定表的约束进行创建、修改和删除。
在修改约束之前,要确保了解并满足新的约束要求,并确保没有数据违反约束。
在删除约束之前,要确保没有数据依赖于该约束,并且备份数据以防止意外的数据损失。
对于某些约束,需要先删除约束才能修改列的定义,然后再重新添加约束。在实际操作中,一定要谨慎处理对表结构的改变,并确保在进行任何更改之前备份数据。
5.1.2注意事项:
在使用主键约束时,需要注意以下几点:
-
唯一性:主键值必须在表中是唯一的。确保每行的主键值都不相同,以避免违反主键约束。如果插入或更新操作导致重复的主键值,将会触发主键冲突错误。
-
非空性:主键列不能为空(即不允许NULL值)。因此,在定义主键约束之前,应该确保列上没有NULL值。如果尝试将NULL值插入主键列,将会触发非空约束错误。
-
不可修改性:主键值一旦设置,通常是不允许更改的。这是为了确保主键的稳定性和数据完整性。如果确实需要更改主键值,那么首先需要删除原有的行,然后插入新的行。
-
主键命名:给主键约束命名时,应该选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"PK_"作为主键约束名称的前缀,以便于识别。
-
引用关系:主键通常被用来建立表与其他表的关联(外键引用)。当表存在外键引用时,删除或修改主键值可能会影响到其他表的数据完整性。在进行任何更改之前,请谨慎评估和处理相关的外键关系。
-
聚集索引:主键约束默认会创建一个聚集索引。聚集索引决定了表中数据的物理存储顺序。要根据查询需求和性能优化考虑是否使用聚集索引,并选择合适的列作为聚集索引的键。
-
复合主键:可以通过使用多个列来定义复合主键。在使用复合主键时,确保每个组合值都是唯一的,并且所有组合值都不为空。
-
自增长主键:可以使用IDENTITY属性或SEQUENCE对象来生成自增长的主键值。自增长主键为每个新行分配一个唯一的、递增的值。要正确使用自增长主键,请确保未手动插入主键值。
总结:
使用主键约束可以确保表中的每行都具有唯一标识并且非空。在使用主键约束时,要注意唯一性、非空性、不可修改性、命名规范以及与其他表的引用关系。这样可以确保数据的完整性和一致性,并提高数据库的性能和可维护性。
5.2.2注意事项:
在使用外键约束时,需要注意以下几点:
-
引用完整性:外键约束用于维护表之间的引用完整性。在定义外键约束之前,应确保所引用的主键或唯一键列存在,并且已经创建了相应的主键或唯一约束。
-
数据一致性:外键约束确保关联表中的数据保持一致。插入或更新包含外键的行时,确保引用值存在于关联表中,以避免违反外键约束。
-
级联操作:可以定义级联操作来处理与外键关联的操作。级联操作指定了当引用表中的数据发生改变时,对关联表中的数据的处理方式。常见的级联操作包括级联删除和级联更新。
-
删除限制:默认情况下,外键约束会阻止删除关联表中被引用的行。如果要删除关联表中的数据,必须首先删除引用它的所有行,或者定义级联删除操作来自动删除相关行。
-
修改限制:默认情况下,外键约束会阻止修改关联表中被引用的主键或唯一键列。如果需要修改关联列的值,必须先删除外键约束,然后进行修改。修改完成后,可以重新创建外键约束。
-
外键命名:给外键约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"FK_"作为外键约束名称的前缀,以便于识别。
-
联接效率:外键约束可能会影响查询的性能。因此,在设计和使用外键时,要注意查询的联接操作,并根据具体需求考虑是否需要创建索引来优化查询性能。
-
外键顺序:在创建多个外键约束时,外键约束的顺序可能会对操作产生影响。如果存在循环引用,即多个表相互引用,必须谨慎处理外键的顺序和依赖关系。
总结:
在使用外键约束时,要确保引用关系的完整性,并注意数据的一致性、级联操作、删除和修改的限制。合理命名外键约束,考虑查询效率和索引的使用,以确保数据库的正常运行和性能优化。
5.3.2注意事项:
唯一约束(Unique Constraint)用于确保列或列组合的值是唯一的,需要注意以下几点:
-
唯一性:唯一约束要求列或列组合中的值在表中是唯一的,不允许重复。确保每行的唯一约束值都不相同,以避免违反唯一性约束。
-
NULL值:唯一约束默认可以包含一个NULL值。这意味着多个NULL值可以存在于列或列组合中而不违反唯一性约束。如果想要禁止NULL值重复,可以创建一个索引来实现。
-
索引创建:唯一约束会自动创建一个唯一索引来支持唯一性验证。确保在设计和使用唯一约束时,对相关列或列组合创建适当的索引,以提高查询效率。
-
复合唯一约束:可以使用多个列来定义复合唯一约束。复合唯一约束意味着多个列的组合必须是唯一的。在创建复合唯一约束时,确保每个组合值都是唯一的,且所有组合值都不为空。
-
唯一约束命名:给唯一约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"UQ_"作为唯一约束名称的前缀,以便于识别。
-
修改限制:修改唯一约束会影响现有数据的一致性。如果要更改唯一约束的列或列组合,必须先删除原有的唯一约束,然后重新创建新的唯一约束。
-
外键引用:唯一约束常用于引用表之间的关系。如果将唯一约束用作外键的引用,需要确保被引用的唯一值与外键列或列组合相匹配,并且满足引用完整性的要求。
-
性能影响:唯一约束的索引可能会对插入、更新和删除操作的性能产生影响。在设计和使用唯一约束时,要平衡数据完整性和性能需求,根据具体情况选择是否使用唯一约束。
总结:
在使用唯一约束时,要确保唯一性、索引的创建和命名、复合唯一约束的定义和数据完整性的保持。同时,需要注意与外键引用、修改约束和性能方面的考虑,以确保数据库的正常运行和性能优化。
5.4.2注意事项:
需要注意以下几点:
-
检查条件:检查约束用于限制列的取值范围。在定义检查约束时,要确保检查条件是准确的、完整的,并且符合业务规则和需求。
-
约束命名:给检查约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"CK_"作为检查约束名称的前缀,以便于识别。
-
多列检查约束:可以使用多个列来定义复杂的检查约束。在使用多列检查约束时,要确保检查条件涵盖了所有相关列,并且能够正确地验证数据的完整性。
-
修改限制:修改检查约束可能会影响现有数据的一致性。如果要更改检查约束的条件,必须先删除原有的检查约束,然后重新创建新的检查约束。
-
性能影响:应谨慎使用复杂或耗时的检查条件,因为它们可能会对插入、更新和查询操作的性能产生影响。在设计和使用检查约束时,要平衡数据完整性和性能需求。
-
默认值冲突:如果存在默认值并且检查约束条件与默认值冲突,将无法插入或更新数据。确保检查约束的条件和默认值是兼容的,并且不会导致冲突。
-
特殊字符转义:如果检查约束条件包含特殊字符,如引号、百分号等,要进行适当的转义处理,以避免语法错误或意外行为。
-
跨表检查约束:检查约束可以跨多个表进行定义。在跨表检查约束时,要确保引用的表和列是正确的,并且能够满足数据完整性和业务规则的要求。
总结:
在使用检查约束时,要确保检查条件的准确性和完整性,合理命名约束,注意修改约束的影响和检查条件与默认值的兼容性。同时,要注意性能方面的考虑,并在需要的情况下进行特殊字符转义和跨表检查约束的定义。这样可以确保数据库中的数据满足业务规则和完整性要求。
.5.2注意事项:
使用默认约束时,需要注意以下几点:
-
默认值选择:默认约束用于指定列在没有明确提供值时的默认值。在选择默认值时,要确保它符合业务规则,并且与列的数据类型兼容。
-
NULL值处理:默认约束可以包含一个NULL值作为默认值。如果想要禁止列使用NULL值作为默认值,可以在创建表时或后续使用ALTER TABLE语句添加NOT NULL约束。
-
默认约束命名:给默认约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"DF_"作为默认约束名称的前缀,以便于识别。
-
修改限制:修改默认约束可能会影响现有数据的一致性。如果要更改默认值,必须先删除原有的默认约束,然后重新创建新的默认约束。
-
多列默认约束:可以为多个列定义相同的默认约束。在使用多列默认约束时,要确保默认值在所有相关列上都是适用的,并且与数据类型兼容。
-
跨表默认约束:默认约束可以跨多个表进行定义。在跨表默认约束时,要确保引用的表和列是正确的,并且能够满足数据完整性和业务规则的要求。
-
性能影响:如果默认值涉及复杂计算或查询操作,可能会对插入和更新操作的性能产生影响。要谨慎选择默认值,避免过度复杂或耗时的操作。
-
默认约束的顺序:如果存在多个默认约束,并且有依赖关系,确保按正确的顺序创建这些约束,以避免依赖错误。
总结:
在使用默认约束时,要选择合适的默认值,注意NULL值的处理、命名约束、修改约束的影响和多列/跨表默认约束的定义。同时,要注意默认值的性能影响和约束的顺序,以确保数据库中的数据具有适当的默认值并满足业务规则。
5.6.2注意事项:
使用非空约束时,需要注意以下几点:
-
列定义:非空约束用于限制列不允许为空值。在定义表结构时,需要明确指定哪些列需要应用非空约束。
-
默认值:如果未提供值且列具有默认值,则非空约束不会阻止插入操作。确保在设计表时,明确为不允许为空的列提供适当的默认值或规定其必须显式提供值。
-
修改限制:如果要将已具有数据的列更改为非空约束,必须先确定所有现有行都包含有效的值,然后才能添加非空约束。
-
空字符串:非空约束只针对空值(NULL),而不会限制空字符串。如果希望禁止空字符串,则需要使用非空约束和额外的检查约束来实现。
-
外键关系:在定义外键关系时,注意引用列是否允许为空。如果主表中的被引用列是非空约束,那么外键列也应该是非空约束,以确保引用完整性。
-
默认约束冲突:如果某个列既有非空约束又有默认约束,并且二者存在冲突,例如默认值为NULL,则会导致冲突。确保默认约束与非空约束兼容,以避免此类冲突。
-
数据完整性:非空约束可确保数据完整性,但需要注意在应用非空约束之前,已经存在的数据可能包含空值。在应用非空约束之后,需要确保现有数据符合约束条件。
-
修改数据:非空约束限制了对该列的更新和插入操作中的空值。确保在进行这些操作时,提供了非空的值,否则将违反非空约束
总结:
在使用非空约束时,要注意对列的定义、默认值的处理,修改限制和数据完整性的考虑。同时,需要注意与外键关系和默认约束的兼容性,以确保数据库中的数据满足非空约束并保持一致性。
sql
CREATE TABLE Employees (
EmployeeID INT NOT NULL,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
-- 添加主键约束
CONSTRAINT PK_Employees PRIMARY KEY (EmployeeID)
);
CREATE TABLE Orders (
OrderID INT IDENTITY(1,1) PRIMARY KEY,
EmployeeID INT,
OrderDate DATE,
-- 添加外键约束,引用Employees表的EmployeeID字段
CONSTRAINT FK_Orders_Employees FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID)
);
CREATE TABLE Users (
UserID INT IDENTITY(1,1) PRIMARY KEY,
Email NVARCHAR(100),
-- 添加唯一约束,确保Email字段的值是唯一的
CONSTRAINT UQ_Users_Email UNIQUE (Email)
);
CREATE TABLE Products (
ProductID INT IDENTITY(1,1) PRIMARY KEY,
ProductName NVARCHAR(100),
Price DECIMAL(10, 2),
-- 添加检查约束,确保价格大于0
CONSTRAINT CK_Products_Price CHECK (Price > 0)
);
1、添加主键约束alter table stuinfo add costraint pk_stuno primary key (stuno)
2、唯一约束alter table stuinfo add constraint uq_stuid unique (stuid)
3、添加默认约束alter table stuinfo add constraint df_address default ('地址不详') for address
4、添加检查约束alter table stuinfo add constraint ck_age check (age between 15 and 40) 这是年龄在15到40之间
5、添加外键约束alter table stumarks add constraint fk_stuno foreign key (stuno) references stuinfo (stuno)这是一个成绩表(stumarks)引用学生信息表中的列 学号
6、not null 非空约束,强制不接受空值,例如,创建表时,name varchar(6) not null
sql
--创建约束
--为性别增加一个检查约束,要求性别只能是:'男' or '女'
alter table AbcTable add constraint CK_AbcTable_EmpGender check(EmpGender='男' or EmpGender='女')
--删除单个约束
alter table AbcTable drop constraint CK_AbcTable_EmpGender
--为EmpName增加一个唯一约束
alter table Employees add constraint UQ_Employees_EmpName unique(EmpName)
--为订单增加检查约束,要求Payment=(PaymentToBId+PaymentToTm)
alter table Trade add constraint CK_Trade_PaymentLargeZero check(Payment>0 and PaymentToBid>0)
alter table Trade add constraint CK_Trade_PaymentToBidToTm check(Payment=(PaymentToBid+PaymentToTm))
alter table [Order] add constraint CK_Order_PaymentToBidToTm check(Payment=(PaymentToBid+PaymentToTm))
alter table ChannelInMoneyFlow add constraint UQ_ChannelInMoneyFlow_InTradePayDate unique(InTradePayDate)
--查找Check约束
select * from sys.check_constraints chk
select * from sys.tables tab
SELECT
tab.name AS [表名],
chk.name AS [Check约束名],
chk.definition
FROM
sys.check_constraints chk
JOIN sys.tables tab
ON (chk.parent_object_id = tab.object_id)
----查找唯一约束
select * from sys.indexes idx where idx.is_unique_constraint = 1
SELECT
tab.name AS [表名],
idx.name AS [约束名称],
col.name AS [约束列名]
FROM
sys.indexes idx
JOIN sys.index_columns idxCol
ON (idx.object_id = idxCol.object_id
AND idx.index_id = idxCol.index_id
AND idx.is_unique_constraint = 1)
JOIN sys.tables tab
ON (idx.object_id = tab.object_id)
JOIN sys.columns col
ON (idx.object_id = col.object_id
AND idxCol.column_id = col.column_id);
----查找外键约束
select * from sys.foreign_keys fk
select
oSub.name AS [子表名称],
fk.name AS [外键名称],
SubCol.name AS [子表列名],
oMain.name AS [主表名称],
MainCol.name AS [主表列名]
from
sys.foreign_keys fk
JOIN sys.all_objects oSub
ON (fk.parent_object_id = oSub.object_id)
JOIN sys.all_objects oMain
ON (fk.referenced_object_id = oMain.object_id)
JOIN sys.foreign_key_columns fkCols
ON (fk.object_id = fkCols.constraint_object_id)
JOIN sys.columns SubCol
ON (oSub.object_id = SubCol.object_id
AND fkCols.parent_column_id = SubCol.column_id)
JOIN sys.columns MainCol
ON (oMain.object_id = MainCol.object_id
AND fkCols.referenced_column_id = MainCol.column_id)