【MySQL|第七篇】DDL语句——数据库定义语言
目录
七、DDL语句
1、创建表:
(1)数据类型:
(2)常见约束:
约束类型
约束分类
(3)特殊建表:
(4)级联动作:
2、修改表:
(1)添加字段:
(2)修改字段:
(3)列重命名:
(4)删除字段:
(5)更改约束:
3、重命名表:
4、删除表:
七、DDL语句
DDL(Data Definition Language)是 SQL 中用于定义和管理数据库对象的语句集合。DDL 语句主要包括 CREATE、ALTER、RENAME、DROP和TRUNCATE 。
1、创建表:
(1)数据类型:
语法:建表的语法有两种:
-- 格式1
create table 表名(
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
...
);
-- 格式2
create table 表名(
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
...
[表级约束],
[表级约束],
...
);
根据以上格式,可以看出,建表过程中,需要以下几种东西:
1. 关键字
2. 表名
3. 列名
4. 数据类型
5. 约束
6. 固定格式
列级约束,表级约束都是对列中的值进行约束限制的
例如,列的值不能为空,列的值必须是唯一的等等
数据类型:
(1)数值类型:
注意:
对于准确性要求较高的字段,比如money,可以用DECIMAL类型,减少存储误差。
声明语法是DECIMAL(M,D),M是数字的最大数字位数,D是小数点右侧数字的位数比如 DECIMAL(6,2)最多存6位数字,小数点后占2位,取值范围-9999.99到9999.99。
(2)文本类型:
注意事项:
1. 普通字符串:CHAR,VARCHAR
2. 存储文本:TEXT
3. 存储二进制数据:BLOB
char:定长,即指定存储字节数后,无论实际存储了多少字节数据,最终都占指定的字节大小。默认只能存1字节数据,存取效率高。
varchar:不定长,效率偏低 ,但是节省空间,实际占用空间根据实际存储数据大小而定。必须要指定存储大小 varchar(50)。
(3)日期类型:
- 日期时间函数
now() 返回服务器当前日期时间,格式对应datetime类型。
- 时间操作
时间类型数据可以进行比较和排序等操作,在写时间字符串时尽量按照标准格式书写。
案例展示:
-- 马拉松比赛登记表 create table marathon (id int primary key auto_increment,name varchar(32),birthday date,register_time datetime,performance time ); insert into marathon values (1,'Jack','1995-2-18','2021-12-18 19:20:20','2:48:58'), (2,'Tony','2000-6-8','2021/12/22 9:30:25','2:29:8'), (3,'Tom','1998-2-28','2022-1-1 16:21:21','2:33:55');select * from marathon where birthday>='2000-01-01'; select * from marathon where birthday>='2000-07-01' and performance<='2:30:00';
(4)额外补充: 存储选项型数据 ENUM,SET 。
ENUM 是一种特殊的数据类型,用于存储固定的选项列表。
案例展示:
-- 删除表 drop table my_table; CREATE TABLE my_table (id INT,option_column ENUM('Option 1', 'Option 2', 'Option 3') ); -- option_column只能添加上述3个值 INSERT INTO my_table(id, option_column) VALUES (1, 'Option 1'); INSERT INTO my_table(id, option_column) VALUES (1, 'Option 4'); SELECT * FROM my_table;
SET 数据类型可以用来存储一组预定义的选项。SET 类型允许你在一个列中存储多个选项值,每个选项值可以被设置为 1(选中)或 0(未选中)。
drop table my_table; CREATE TABLE my_table (id INT,options SET('Option 1', 'Option 2', 'Option 3') ); -- options可以同时添加多个值 INSERT INTO my_table(id, options) VALUES (2, 'Option 1,Option2'); SELECT * FROM my_table; -- 查询包含特定选项的行,可以使用 FIND_IN_SET() 函数 -- 例如,要查找包含 "Option 2" 的行,可以执行以下查询: SELECT * FROM my_table WHERE FIND_IN_SET('Option 2', options) > 0;
(2)常见约束:
数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的,为了保证数据的完整性,SQL规范以约束的方式对表数据进行额外的条件限制 。包括:
- 实体完整性(Entity Integrity)
如:同一个表中,不能存在两条完全相同无法区分的记录域完整性(Domain Integrity)
如:性别男、女;星期为星期一~星期日
- 引用完整性(Referential Integrity)
如:员工能基于员工表找到部门,同样基于部门表可以找到区域
- 用户自定义完整性(User-Defined Integrity)
如:员工的名字不能不为空,唯一,员工薪水不能高于经理薪水
约束的本质是对表中数据的限制和关系的维护,具体介绍如下。
约束类型
NOT NULL
设置的列不能为空,换言之必须有值,所有类型的默认值都为null;
NOT NULL只能用于列级约束不能用于表级约束
所有类型和null进行运算都为null
UNIQUE
用来限制某个字段/某列的值不能重复 。
唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一
创建唯一约束,不指定约束名字,mysql基于列名作为约束名
唯一性约束允许列值为空
唯一性约束默认自带索引
PRIMARY KEY
用来唯一标识表中的一行记录,其特点:
主键约束列不允许重复,也不允许出现空值。
一个表最多只能有一个主键约束
主键约束对应着表中的一列或者多列,组合列同样不允许重复,也不允许出现空值
创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引
删除主键约束了,主键约束对应的索引就自动删除了
FOREIGN KEY
外键约束,维护表与表之间的关系
语法:
//方法1 create table tb_name1(col_name type primary key,col_name1 type); //方法2 create table tb_name2(col_name type primary key,col_name1 type,col_name2 type[constraint fg_name] foreign key(col_name2) referencestb_name1(col_name) [on update [cascade|set null][on delete[cascade|set null]]);
注意事项:
外键用于维护表与表之间的关系,外键必须引用另外一张表的主键或唯一约束列。
创建外键约束时,如果不给外键约束命名, 默认名不是列名,而是自动产生一个外键名。
创建表时就指定外键约束的话,先创建主键约束的表,再创建外键的表。
删表时,先删外键的表,再删除主键表 ,删除数据同理。
一张表可以创建多个外键,引用多个不同的表的主键维护关系。
创建外键约束时,系统默认会在所在的列上建立对应的普通索引 。但是索引名是外键的约束名。
删除外键约束后,必须手动删除对应的索引
外键和主键类型必须一致
CHECK
检查某个字段的值是否符某要求,一般指的是值的范围 ;
MySQL5.7 可以使用check约束,但check约束对数据验证没有任何作用。添加数据时,没有任何错误或警告
MySQL 8.0中可以使用check约束
DEFAULT
给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值。默认值约束一般不在唯一键和主键列上加。
注意事项:
1. MySQL5.7不支持check约束,但可以使用check约束,而没有任何效果 ;
2. MySQL8.0支持check约束
约束分类
表级约束
//表既约束
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(字段1 数据类型 ,字段2 数据类型 ,字段3 数据类型 ,......[constraint 约束名] 表级约束[constraint 约束名] 表级约束......)]engine=innodb default charset=utf8
列级约束
//列级约束
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name[(字段1 数据类型 [列级约束] ,字段2 数据类型 [列级约束] ,字段3 数据类型 [列级约束] ,...)]engine=innodb default charset=utf8;
案例展示:
1、普通的建表例子
create table student(id int primary key,name varchar(200) not null,age int,birthday date);drop table student;
2、使用四种列级约束 主键约束 非空约束 唯一约束 check约束
create table student(id int primary key,name varchar(100) not null,email varchar(100) unique,gender char(1) check(gender in('f','m')),age int,birthday date);-- 插入数据验证约束insert into student(id,name,email,gender) values(1,'tom','tom@qq.com','f');insert into student(id,name,email,gender) values(2,'jack','jack@qq.com','m');insert into student(id,name,email,gender) values(3,'lucy','lucy@qq.com','n');drop table student;
表级约束基础的案例:
注意事项:非空约束(not null),不能声明成表级约束
1、表级约束基础:
create table student(id int,name varchar(20) not null,age int default 20,email varchar(100),gender char,primary key(id),unique(email),check(gender in('f','m')));drop table student;
2、使用表级约束声明外键约束
drop table if exists t_order;drop table if exists t_customer;create table t_customer(id int primary key,name varchar(200) not null);insert into t_customer values(1,'zs'),(2,'ls'),(3,'ww'),(4,'lucy');create table t_order(id int primary key,content varchar(200) not null,customer_id int,foreign key(customer_id) references t_customer(id));insert into t_order values(1,'xiaomi',1),(2,'huawei',2),(3,'phone',3);-- 此时删除失败,因为另一张表 引用了该条记录delete from t_customer where id = 3;
注意事项:
- 订单表中的外键列customer_id的值,是引用自顾客表t_customer中的主键列id的值
- 这时候直接删除顾客表是不行的,因为t_customer的主键列的值被别的表给引用了
- 可以先删除订单表t_order,然后再删除t_customer就可以了
- cascade是级联的意思,后续章节会重点讨论
表级约束和列级约束对比:
1. 表级约束和列级约束所写的位置不一样
2. not null约束不能用表级约束来声明
3. 表级约束和列级约束声明语法稍有所不同
4. 如果要声明的约束为联合主键、联合外键、联合唯一的时候,就一定要用表级约束
5. 新版本外键约束只能为表级约束
案例1:创建夫妻表(一对一)
create table hus(id int primary key,name varchar(20));create table wife(id int primary key,name varchar(20),hus_id int,constraint hus_fk foreign key(hus_id) references hus(id));insert into hus values(1,'jake');insert into wife values(1,'rose',1);-- 执行成功,外键列可以为nullinsert into wife(id,name) values(2,'lily');-- 执行报错,不存在2号丈夫insert into wife values(3,'rose',2);
注意事项:
1. 外键值必须在另外一张表存在,且是主键或唯一键
2. 一对一关系可以在任意一方维护(外键可以建任意一方)
案例2:创建员工表和部门表(一对多)
create table dept(id int primary key,name varchar(20));create table emp(id int primary key,name varchar(20),salary double,dept_id int,foreign key(dept_id) references dept(id));insert into dept values(1,'bigdata');insert into emp values(1,'lisi',3000,1);insert into emp values(2,'wangwu',3200,1);insert into emp values(3,'zhansan',2800,1);
案例3:创建学生表和课程表(多对多)
create table stu(id int primary key,name varchar(20));create table course(id int primary key,name varchar(20));create table stu_cou(stu_id int,course_id int,foreign key(stu_id) references stu(id),foreign key(course_id) references course(id),primary key(stu_id,course_id));insert into stu values(1,'lisi');insert into stu values(2,'zhansan');insert into course values(1,'java');insert into course values(2,'xml');insert into course values(3,'hadoop');insert into course values(4,'hbase');insert into course values(5,'zookeeper');insert into course values(6,'kafka');insert into stu_cou values(1,1);insert into stu_cou values(1,2);insert into stu_cou values(1,3);insert into stu_cou values(1,4);insert into stu_cou values(2,1);insert into stu_cou values(2,3);insert into stu_cou values(2,4);insert into stu_cou values(2,5);insert into stu_cou values(2,6);

(3)特殊建表:
案例1:建立一张表和s_dept一模一样,s_dept的表结构和表中的数据全部复制过来
create table test1asselect * from s_dept;
案例2:建立一张表和s_dept一模一样,只拿来s_dept的表结构,没有数据
create table test2asselect * from s_deptwhere 1=2;
案例3:建立一张表和s_dept一模一样,只复制表中某几个指定列的数据
create table test3asselect id,last_name,salaryfrom s_emp;
(4)级联动作:
- restrict(默认) : on delete restrict on update restrict
当主表删除记录时,如果从表中有相关联记录则不允许主表删除
当主表更改主键字段值时,如果从表有相关记录则不允许更改
- cascade:数据级联更新 on delete cascade on update cascade
当主表删除记录或更改被参照字段的值时,从表会级联更新
- set null : on delete set null on update set null
当主表删除记录时,从表外键字段值变为null
当主表更改主键字段值时,从表外键字段值变为null
具体案例:
请回顾之前案例, delete from t_customer where id = 3; 会报错。
drop table if exists t_order;
drop table if exists t_customer;
create table t_customer(id int primary key,name varchar(200) not null
);
insert into t_customer values(1,'zs'),(2,'ls'),(3,'ww');
create table t_order(id int primary key,content varchar(200) not null,customer_id int,foreign key(customer_id) references t_customer(id) ON DELETE CASCADE
);
insert into t_order values(1,'xiaomi',1),(2,'huawei',2),(3,'phone',3);
-- 此时会级联删除t_order中相关数据
delete from t_customer where id = 3;
select * from t_order;
2、修改表:
语法:alter table 表名 执行动作;
* 添加字段(add)
alter table 表名 add 字段名 数据类型;
alter table 表名 add 字段名 数据类型 first;
alter table 表名 add 字段名 数据类型 after 字段名;
* 删除字段(drop)
alter table 表名 drop 字段名;
* 修改数据类型(modify)
alter table 表名 modify 字段名 新数据类型;
* 修改字段名(change)
alter table 表名 change 旧字段名 新字段名 新数据类型;
* 修改约束
alter table 表名 add constraint 约束名 具体约束;
(1)添加字段:
语法:
alter table tb_name add [column] col_name type [first|after col_name];
建一个表,举例用:
create table user3(
id int
);
案例1:在表user3中添加列name。
alter table user3 add name varchar(20);desc user3;
案例2:在表user3中第一列的位置插入uid。
alter table user3 add column uid int first;desc user3;
(2)修改字段:
语法:
alter table tb_name modify [column] col_name type [default 默认值];
案例:将表user3中的uid修改为字符串类型,默认值为1
alter table user3 modify column uid varchar(32) default '1';
desc user3;
注意事项:对默认值的修改只影响今后对表的修改,如果原表中有数据,类型不允许修改。
(3)列重命名:
语法:
alter table tb_name change [column] old_col_name new_col_name type;
案例:将表user3中的name修改为username类型
alter table user3 change column name username text;
desc user3;
(4)删除字段:
语法:
alter table tb_name drop [column] col_name;
案例:将表user3中的age列删除
alter table user3 drop column age;
(5)更改约束:
查询约束SQL语句:
select constraint_name,constraint_type
from information_schema.table_constraints
where table_name = '表名';
删除或新增约束语法:
-- 添加主键约束(约束名无效)
alter table 表名 add [constraint 约束名] primary key(列名);
-- 添加唯一约束
alter table 表名 add constraint 约束名 unique(列名);
-- 添加外键约束
alter table 表名 add constraint 约束名 foreign key(列名) references
关联的表名(关联的列名 一般是主键);
-- 删除约束(不能删除主键约束)
alter table 表名 drop constraint 约束名;
案例测试:
-- 删除t_user表drop table if exists t_user;-- 新建t_user表create table t_user(name varchar(30) not null,age int,cid int);-- 添加id列alter table t_useradd column id int first;-- 查看表结构desc t_user;-- 修改id列为主键列alter table t_user add primary key(id);-- 给name添加唯一约束alter table t_user add constraint user_name_un unique(name);desc t_user;-- 删除name唯一约束alter table t_user drop constraint user_name_un;desc t_user;-- 给cid添加外键约束alter table t_user add constraint user_cid_fk foreign key(cid) references t_customer(id);desc t_user;-- 删除外键约束alter table t_user drop constraint user_cid_fk;
3、重命名表:
语法:
rename table old_tb_name to new_tb_name;
或
alter table old_tb_name rename [to] new_tb_name;
案例1:将表user1修改名字为my_user1;
rename table user1 to my_user1;
4、删除表:
语法:
drop table [if exists] tb_name [, tb_name1, ..., tb_namen];
if exists 的含义为:如果当前数据库中存在相应的数据表,则删除数据表; 如果当前数据库中不存,在相应的数据表,则忽略删除语句,不再执行删除数据表的操作。
案例1:删除用户表my_user1;
drop table if exists my_user1;
注意事项:
- 删除表的时候当前表不能被其它表引用
- 数据、结构、索引全都被删除
- 5.7版本删除一批表,其中表不存在也能成功执行,8.0版本必须保证表存在 才可以删除。