SQL-高级命令(二)约束(Constraints)

SQL 约束(Constraints) 

SQL 约束用于规定表中的数据规则

约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)

CREATE TABLE table_name
(
column_name1 data_type(size) constraint_name,
column_name2 data_type(size) constraint_name,
column_name3 data_type(size) constraint_name,
....
);

在 SQL 中,我们有如下约束:

(1)NOT NULL - 指示某列不能存储 NULL 值

(2)UNIQUE - 保证某列的每行必须有唯一的值

(3)PRIMARY KEY(简称PK)- NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录

(4)FOREIGN KEY(简称FK)- 保证一个表中的数据匹配另一个表中的值的参照完整性

(5)CHECK - 保证列中的值符合指定的条件

(6)DEFAULT - 规定没有给列赋值时的默认值

列级约束:约束单个字段

表级约束: 约束多个字段


1、SQL NOT NULL 约束

NOT NULL 约束强制列不接受 NULL 值

CREATE TABLE Persons (
    ID int NOT NULL,
    Age int
);

 如果给字段加了not null 约束,插入数据时没给值,就会报错

insert into user(name) values('admin');

ERROR 1364 (HY000): Field 'name' doesn't have a default value

添加 NOT NULL 约束

ALTER TABLE Persons
MODIFY Age int NOT NULL;

删除 NOT NULL 约束

ALTER TABLE Persons
MODIFY Age int NULL;

2、SQL UNIQUE 约束

UNIQUE 约束唯一标识数据库表中的每条记录

UNIQUE 约束的字段不能重复,但是可以为NULL

UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证。

PRIMARY KEY 约束拥有自动定义的 UNIQUE 约束。

注:

每个表可以有多个 UNIQUE 约束;但是每个表只能有一个 PRIMARY KEY 约束

约束单列

MySQL:

CREATE TABLE Persons
(
    P_Id int NOT NULL,
    Address varchar(255),
    UNIQUE (P_Id)
)

(1)只约束一个字段,属于列级约束;如果约束多个字段,则为表级约束,如下同时约束name 和 email两个字段

drop table if exists user;
create table t_vip(
    id int,
    name varchar(255),
    email varchar(255),
    unique(name,email) // 约束没有添加在列的后面,这种约束被称为表级约束
);

(2)unique 和 not null 联合使用

drop table if exists user;
create table user(
    id int not null unique,
    name varchar(255) 
);

mysql> desc user;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int(11)      | NO   | PRI | NULL    |       |
| name  | varchar(255) | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+

这时会发现变成了主键

 在mysql当中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键字段。(oracle中不一样)

SQL Server / Oracle / MS Access:

CREATE TABLE Persons
(
P_Id int NOT NULL UNIQUE,
Address varchar(255)
)

约束多列

MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons
(
P_Id int NOT NULL,
Address varchar(255),
City varchar(255),
CONSTRAINT uc_PersonID UNIQUE (P_Id,Address)
)

ALTER TABLE 时的 SQL UNIQUE 约束

MySQL / SQL Server / Oracle / MS Access:

单列
ALTER TABLE Persons
ADD UNIQUE (P_Id)

MySQL / SQL Server / Oracle / MS Access:

多列
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,Address)

撤销 UNIQUE 约束

MySQL:

ALTER TABLE Persons
DROP INDEX uc_PersonID

SQL Server / Oracle / MS Access:

ALTER TABLE Persons
DROP CONSTRAINT uc_PersonID

3、SQL PRIMARY KEY 约束

PRIMARY KEY 约束唯一标识数据库表中的每条记录

主键必须包含唯一的值

主键列不能包含 NULL 值

每个表都应该有一个主键,并且每个表只能有一个主键

(1)CREATE TABLE 时的 SQL PRIMARY KEY 约束

在 "Persons" 表创建时在 "P_Id" 列上创建 PRIMARY KEY 约束

MySQL:

CREATE TABLE Persons
(
P_Id int NOT NULL,
Address varchar(255),
PRIMARY KEY (P_Id)
)

 如下:

drop table if exists user;
		// 1个字段做主键,叫做:单一主键
		create table user(
			id int primary key,  //列级约束
			name varchar(255)
		);

或者

drop table if exists user;
		create table user(
			id int,
			name varchar(255),
			primary key(id)  // 表级约束
		);

 不能为null,也不能重复

//错误:不能重复
insert into user(id,name) values(2,'wangwu');
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'

//错误:不能为NULL
insert into user(name) values('zhaoliu');
ERROR 1364 (HY000): Field 'id' doesn't have a default value

单一主键:唯一的1个字段做主键

复合主键: 多个字段联合作为主键

在实际开发中不建议使用:复合主键;主键值存在的意义就是唯一标识数据库表中的每条记录

(1)一张表,主键约束只能添加1个

drop table if exists user;
		create table user(
			id int primary key,
			name varchar(255) primary key
		);
		
ERROR 1068 (42000): Multiple primary key defined

(2)主键值建议使用:int,bigint,char 等类型

不建议使用:varchar来做主键;主键值一般都是数字,一般都是定长的

(3)主键除了:单一主键和复合主键之外,还可以如下分类

自然主键:主键值是一个自然数,和业务没关系

业务主键:主键值和业务紧密关联,例如拿银行卡账号做主键值

在实际开发中使用自然主键,主键只要做到不重复就行,主键一旦和业务挂钩,那么当业务发生变动的时候,可能会影响到主键值

(4)auto_increment 自动维护主键值

drop table if exists user;
create table user(
    id int primary key auto_increment, //auto_increment表示自增,从1开始,以1递增!
    name varchar(255)
);

SQL Server / Oracle / MS Access:

CREATE TABLE Persons
(
P_Id int NOT NULL PRIMARY KEY,
Address varchar(255)
)

名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束

MySQL / SQL Server / Oracle / MS Access

CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
Address varchar(255),
CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
)

注:在上面的实例中,只有一个主键 PRIMARY KEY(pk_PersonID)。然而,pk_PersonID 的值是由两个列(P_Id 和 LastName)组成的

(2)ALTER TABLE 时的 SQL PRIMARY KEY 约束

当表已被创建时,如需在 "P_Id" 列创建 PRIMARY KEY 约束

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons
ADD PRIMARY KEY (P_Id)

命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

注 :使用 ALTER TABLE 语句添加主键,必须把主键列声明为不包含 NULL 值(在表首次创建时)

(3)撤销 PRIMARY KEY 约束

MySQL:

ALTER TABLE Persons
DROP PRIMARY KEY

SQL Server / Oracle / MS Access:

ALTER TABLE Persons
DROP CONSTRAINT pk_PersonID

4、SQL FOREIGN KEY 约束

一个表中的 FOREIGN KEY 指向另一个表中的 UNIQUE KEY(唯一约束的键)

"Persons" 表:

P_IdLastNameAddressCity
1HansenTimoteivn 10Sandnes
2SvendsonBorgvn 23Sandnes
3PettersenStorgt 20Stavanger

"Orders" 表:

O_IdOrderNoP_Id
1778953
2446783
3224562
4245621

"Orders" 表中的 "P_Id" 列指向 "Persons" 表中的 "P_Id" 列。

"Persons" 表中的 "P_Id" 列是 "Persons" 表中的 PRIMARY KEY。

"Orders" 表中的 "P_Id" 列是 "Orders" 表中的 FOREIGN KEY。

FOREIGN KEY 约束用于预防破坏表之间连接的行为。

FOREIGN KEY 约束也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。

当两张表存在关联字段的时候,利用外键可以保证主表和从表的一致性和完整性

(1)CREATE TABLE 时的 SQL FOREIGN KEY 约束

在 "Orders" 表创建时在 "P_Id" 列上创建 FOREIGN KEY 约束:

MySQL:

CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)

如下,创建了学生表和班级表,学生的班级号就是班级表的班级号

drop table if exists t_student;
drop table if exists t_class;

//创建班级表
create table class(
	classno int primary key,
	classname varchar(255)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

//创建学生表
create table student(
	no int primary key auto_increment,
	name varchar(255),
	cno int,
	foreign key(cno) references class(classno) //外键:学生表的cno 关联 班级表的 classNo 字段
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

当cno字段没有任何约束的时候,可能会导致数据无效。如班级号102不存在;为了保证cno字段中的值都是100和101,需要给cno字段添加外键约束

insert into student(name,cno) values('zhaolin', 102);

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mydb`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`cno`) REFERENCES `class` (`classno`))

子表中的外键引用的父表中的某个字段,被引用的这个字段不一定是主键,但至少具有unique约束 

外键值可以为null

class是父表;student是子表

先删子表,再删父表

先创建父表,再创建子表

先删子表数据,再删父表数据

先插入父表数据,再插入子表数据

SQL Server / Oracle / MS Access:

CREATE TABLE Orders
(
O_Id int NOT NULL PRIMARY KEY,
OrderNo int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)

如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束

MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)

(2)ALTER TABLE 时的 SQL FOREIGN KEY 约束

当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders
ADD FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)

如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)

(3)撤销 FOREIGN KEY 约束

如需撤销 FOREIGN KEY 约束

MySQL:

ALTER TABLE Orders
DROP FOREIGN KEY fk_PerOrders

SQL Server / Oracle / MS Access:

ALTER TABLE Orders
DROP CONSTRAINT fk_PerOrders

5、SQL CHECK 约束

CHECK 约束用于限制列中的值的范围。

如果对单个列定义 CHECK 约束,那么该列只允许特定的值。

如果对一个表定义 CHECK 约束,那么此约束会基于行中其他列的值在特定的列中对值进行限制

(1)CREATE TABLE 时的 SQL CHECK 约束

在 "Persons" 表创建时在 "P_Id" 列上创建 CHECK 约束。CHECK 约束规定 "P_Id" 列必须只包含大于 0 的整数。

MySQL:

CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
City varchar(255),
CHECK (P_Id>0)
)

SQL Server / Oracle / MS Access:

CREATE TABLE Persons
(
P_Id int NOT NULL CHECK (P_Id>0),
LastName varchar(255) NOT NULL,
City varchar(255)
)

如需命名 CHECK 约束,并定义多个列的 CHECK 约束

MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
City varchar(255),
CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
)

(2)ALTER TABLE 时的 SQL CHECK 约束

当表已被创建时,如需在 "P_Id" 列创建 CHECK 约束

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons
ADD CHECK (P_Id>0)

如需命名 CHECK 约束,并定义多个列的 CHECK 约束

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persons
ADD CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')

(3)撤销 CHECK 约束

如需撤销 CHECK 约束,请使用下面的 SQL:

SQL Server / Oracle / MS Access:

ALTER TABLE Persons
DROP CONSTRAINT chk_Person

MySQL:

ALTER TABLE Persons
DROP CHECK chk_Person

6、SQL DEFAULT 约束

DEFAULT 约束用于向列中插入默认值

(1)CREATE TABLE 时的 SQL DEFAULT 约束

在 "Persons" 表创建时在 "City" 列上创建 DEFAULT 约束:

My SQL / SQL Server / Oracle / MS Access:

CREATE TABLE Persons
(
    P_Id int NOT NULL,
    LastName varchar(255) NOT NULL,
    City varchar(255) DEFAULT 'Sandnes'
)

通过使用类似 GETDATE() 这样的函数,DEFAULT 约束也可以用于插入系统值:

CREATE TABLE Orders
(
    O_Id int NOT NULL,
    OrderNo int NOT NULL,
    P_Id int,
    OrderDate date DEFAULT GETDATE()
)

(2)ALTER TABLE 时的 SQL DEFAULT 约束

当表已被创建时,如需在 "City" 列创建 DEFAULT 约束

MySQL:

ALTER TABLE Persons
ALTER City SET DEFAULT 'SANDNES'

SQL Server / MS Access:

ALTER TABLE Persons
ADD CONSTRAINT ab_c DEFAULT 'SANDNES' for City

Oracle:

ALTER TABLE Persons
MODIFY City DEFAULT 'SANDNES'

(3)撤销 DEFAULT 约束

如需撤销 DEFAULT 约束

MySQL:

ALTER TABLE Persons
ALTER City DROP DEFAULT

SQL Server / Oracle / MS Access:

ALTER TABLE Persons
ALTER COLUMN City DROP DEFAULT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值