1 条件查询
1.1 常用方法
- distinct
使用distinct关键字,去除重复的记录行
SELECT loc FROM dept; #查询dept表中loc列的数据
SELECT DISTINCT loc FROM dept; #查询dept表中去除相同内容的loc列的数据
- where
注意:where中不能使用列别名!!
select * from emp
select * from emp where 1=1 --类似没条件,所有的数据都符合此条件,输出所有数据
select * from emp where 1=0 --条件不成立,所有的数据都不符合此条件,所有数据都不输出
select * from emp where empno=100 --唯一条件,查询emp表中,部门编号等于100的数据
select * from emp where empno>100 --查询emp表中,部门编号大于100的数据
select * from emp where ename='tony' and deptno=2 --相当于两个条件的&关系
select * from emp where ename='tony' or deptno=1 --相当于两个条件的|关系
select name, sal from emp where sal=1400 or sal=1600 or sal=1800;
-- 或
select name, sal from emp where sal in(1400,1600,1800); --查查询emp表中,sal等于1400,1600,1800的数据,并输出符合条件的 name, sal
select name, sal from emp where sal not in(1400,1600,1800);--查查询emp表中,sal不等于1400,1600,1800的数据,并输出符合条件的 name, sal
- like
通配符%代表0到n个字符,通配符下划线_代表1个字符
select * from emp where ename like 'l%' --模糊查询,以l开头的
select * from emp where ename like '%a' --模糊查询,以a结束的
select * from emp where ename like '%a%' --模糊查询,中间包含a的
select * from emp where ename like 'l__' --模糊查询,l后面有两个字符的, _代表一个字符位置
- null
查询没有奖金的员工信息
SELECT * FROM emp WHERE comm IS NULL;--注意此处不能用=,要用is
查询有奖金的员工信息
SELECT * FROM emp WHERE comm IS NOT NULL;
- between and
SELECT * FROM emp
select * from emp where sal>5000 and sal>10000 --查询工资大于5000且小于10000的员工信息
SELECT * FROM emp WHERE sal<5000 OR sal>10000;--查询工资大于5000或小于10000的员工信息
select * from emp where sal<=3000 and sal>=10000--查询工资大于等于3000且小于等于10000的员工信息
SELECT * FROM emp WHERE sal<=3000 OR sal>=10000;--查询工资大于等于3000或小于等于10000的员工信息
select * from emp where sal between 5000 and 10000--查询工资大于等于5000,小于等于10000的员工信息
- limit
分数最高的记录:按分数排序后,limit n,返回前n条。Oracle做的很笨,实现繁琐,后期有介绍,而mysql做的很棒,语法简洁高效。在mysql中,通过limit进行分页查询:
select * from emp limit 2 --列出前两条
select * from emp limit 1,2 --从第二条开始,展示2条记录
select * from emp limit 0,3 --从第一条开始,展示3条记录--前三条
- order by
SELECT * FROM emp order by sal #默认升序
SELECT * FROM emp order by sal desc #降序
SELECT * FROM emp ORDER BY ename DESC #按照字母降序
SELECT * FROM emp ORDER BY hiredate DESC #按照时间的数字降序
SELECT * FROM emp ORDER BY ename DESC; #汉字排序时,会根据utf-8中汉字的编码数字进行排序,需要注意
1.2 测试案例一
#limit:分页,限制数据展示的条目
#展示两条员工信息
SELECT * FROM emp LIMIT 2 #取前几条
SELECT * FROM emp LIMIT 2,3#从n+1条数据开始展示,总共展示的条数
#order by:排序,默认升序asc,降序DESC--字典顺序
SELECT * FROM emp ORDER BY sal ASC #按照sal排序,默认升序
SELECT * FROM emp ORDER BY sal DESC #降序
SELECT * FROM emp ORDER BY ename #按照字母升序顺序
SELECT * FROM emp ORDER BY hiredate #按照数字大小升序排
SELECT * FROM emp ORDER BY job
#了解::汉字排序时会查utf8里对应的数字,按照数字升序排序
#统计需求:
#练习1:统计2019年以前入职的员工信息
SELECT * FROM emp WHERE hiredate<'2019-1-1'
SELECT * FROM emp WHERE YEAR(hiredate)<2019
#练习2:统计员工的年薪
SELECT sal,comm,sal*13+IFNULL(comm,0)*13 年薪 FROM emp
1.3 测试案例二
#常见的业务中:增删改查CRUD,其中查询需求最多
#条件查询:
#1.distinct把数据去重
SELECT DISTINCT loc FROM dept
#2.where用来引导判断条件
#select ? from ? where ?
#练习1:查询部门编号=40的数据
SELECT * FROM dept WHERE deptno=40
SELECT * FROM dept WHERE deptno=40000
#练习2:查询部门编号>10的数据
SELECT * FROM dept WHERE deptno>10
SELECT * FROM dept WHERE 1=1 #条件永远成立
#练习3:查询部门编号>10并且地址在二区的数据
SELECT * FROM dept WHERE deptno>10 AND loc='二区'
#练习4:查询部门编号>10或者地址在二区的数据
SELECT * FROM dept WHERE deptno>10 OR loc='二区'
#练习5:查询部门编号=10的或者=20的或者=30的数据
SELECT * FROM dept WHERE
deptno=10 OR deptno=20 OR deptno=30
#同上的需求,被简化--in子句
SELECT * FROM dept WHERE deptno IN(10,30)#查deptno=10 or deptno=30的
SELECT * FROM dept WHERE deptno NOT IN(10,20,30)
#3.like模糊查询 %是通配符,通配0~n个字符
#练习1:查询按照员工名字以l开头员工信息
SELECT * FROM emp WHERE ename LIKE 'l%' #以l开头
#练习2:查询按照员工名字包含o 的员工信息
SELECT * FROM emp WHERE ename LIKE '%o%' #中间包含o
#练习3:查询按照员工名字以a结尾 的员工信息
SELECT * FROM emp WHERE ename LIKE '%a' #以a结尾
#4.null数据的处理
#练习1:查询没有奖金的员工信息
SELECT * FROM emp WHERE comm IS NULL
#练习2:查询有奖金的员工信息
SELECT * FROM emp WHERE comm IS NOT NULL
#5.between...and在区间范围内的数据
#练习1:查询工资范围在5000~10000内的员工信息
SELECT * FROM emp WHERE sal>5000 AND sal<10000 #(5000,10000)
SELECT * FROM emp WHERE sal BETWEEN 5000 AND 10000 #[5000,10000]
2 统计案例
入职统计
2019年以前入职的老员工
SELECT * FROM emp WHERE hiredate<"2019-1-1";
SELECT * FROM emp WHERE YEAR hiredate<"2019-1-1";
SELECT * FROM emp WHERE DATE_FORMAT(hiredate,'%Y-%m-%d')<'2019-01-01';
SELECT * FROM emp WHERE YEAR(hiredate)<2019
2019年以后签约的员工,日期进行格式转换后方便比较
SELECT * FROM emp WHERE YEAR(DATE_FORMAT(hiredate,'%Y-%m-%d'))>=2019;
2015年到2019年入职的员工
SELECT * FROM emp
WHERE
STR_TO_DATE(hiredate,'%Y-%m-%d')<='2015-01-01'
AND
STR_TO_DATE(hiredate,'%Y-%m-%d')<='2019-12-31'
年薪统计
公司福利不错13薪,年底双薪,统计员工的年薪=sal13+comm13
SELECT empno,ename,job,sal*13+comm*13 FROM emp;
SELECT ename, sal , comm, sal+ifnull(comm,0) from emp;--用0替换掉null
SELECT empno,ename,job,sal*13+comm*13 as 年薪 FROM emp;--用as给列起个别名
SELECT empno,ename,job,sal*13+comm*13 年薪 FROM emp; --as也可以省略
SELECT empno,ename,job,sal*13+IFNULL(comm,0)*13 AS 年薪 FROM emp;--计算总的年薪,遇到null值将其定义为0,创建别名年薪输出数据
3 聚合函数 aggregation
3.1 概述
把一列的所有值聚合起来,然后做数据分析
3.2 常见的聚合函数
- count
select count(sal) from emp; --统计个数,统计个数,基础写法
select count(*) from emp; --效果一样,统计个数,是固定写法,相对低效一些
select count(1) from emp; --效果一样,统计个数,是固定写法,比*要高效
select count(comm) from emp --注意,count统计只统计非null字段
- max / min
select max(sal) from emp --求字段的最大值
select max(sal) ,max(comm) from emp;--求最大值
select max(sal) sal,max(comm) comm from emp;--求最大值,了解此俩种写法的区别
select min(sal) min from emp --获取最小值
select min(sal) min,max(sal) max from emp --最小值最大值
SELECT ename,MAX(sal) FROM emp group by ename --分组
- sum / avg
select count(*) from emp --总记录数
select sum(sal) from emp --求和
select avg(sal) from emp --平均数
3.3 测试案例
#1.聚合函数:把一列的所有值聚合在一起
SELECT sal FROM emp#查询员工工资
SELECT MAX(sal) FROM emp #查询最高工资
SELECT MIN(sal) FROM emp #查询最低工资
#SUM查询工资总和,AVG平均工资
SELECT SUM(sal),AVG(sal) FROM emp
#count()统计总记录数
SELECT COUNT(sal) FROM emp
SELECT COUNT(comm) FROM emp #不统计null元素
SELECT COUNT(*) FROM emp #低效
SELECT COUNT(1) FROM emp #高效
4 分组 group
4.1 用于对查询的结果进行分组统计
4.2 常用的分组函数方法
group by表示分组, having 子句类似where过滤返回的结果
- group by
每个部门每个岗位的最高薪资和平均薪资,结果中的非聚合列必须出现在分组中,否则业务意义不对,有些sql不会报错,但输出数据是有问题的- 什么时候分组? – 查询时出现了混合列
- 按照什么分组? --按照非聚合列分组
SELECT deptno,MAX(sal),AVG(sal) FROM emp GROUP BY deptno; #按照deptno分组,输出聚合列sal和非聚合列deptno;
SELECT job,MAX(sal),AVG(sal) FROM emp GROUP BY job; #按照job分组,输出聚合列sal和非聚合列job;
SELECT deptno,job,MAX(sal),AVG(sal) FROM emp GROUP BY deptno,job; #deptno和job都满足的,输出聚合列sal和非聚合列sal;
SELECT COUNT(1)FROM emp GROUP BY deptno; --统计每个部门的员工人数
SELECT YEAR(hiredate),COUNT(1) FROM emp GROUP BY YEAR(hiredate); --统计每年入职的人数
SELECT deptno,MAX(sal) FROM emp GROUP BY deptno; --统计每个部门的最高薪水
- having
# 平均工资小于8000的部门
select deptno, AVG(sal) from emp
group by deptno #按部门费聚合列分组
having AVG(sal)<8000 #查询条件,类似where,但是group by后的过滤只能配合having
# 统计每年入职的人数,只要人数>1的记录
SELECT COUNT(1) b ,YEAR(hiredate) a FROM emp
GROUP BY a
HAVING b>1;
4.3 测试
#1,分组:group by,把数据按照维度分组,后,数据分析
#口诀:
#什么时候要分组?查询时出现了混合列
#按照什么分组?按照非聚合列分组
#练习1:统计每个岗位的平均薪资
SELECT job,AVG(sal) FROM emp GROUP BY job
#练习2:统计每个部门的员工人数
SELECT deptno,COUNT(1) FROM emp GROUP BY deptno
#练习3:统计每年入职的人数
SELECT YEAR(hiredate),COUNT(1) FROM emp GROUP BY YEAR(hiredate)
#练习4:统计每个部门的最高薪
SELECT deptno,MAX(sal) FROM emp GROUP BY deptno
#2.分组后过滤having
#练习1:统计每个部门的最高薪,只要>10000的记录
SELECT MAX(sal) a,deptno FROM emp
GROUP BY deptno #按照非聚合列分组
HAVING a>10000 #group by后的过滤必须用having
#练习2:统计每年入职的人数,只要人数>1的记录
SELECT COUNT(1),YEAR(hiredate) a FROM emp
#where COUNT(1)>1
#where里不能用别名,不能出现聚合函数,比having高效
GROUP BY a # 按照非聚合列a分组
HAVING COUNT(1)>1 # 按照人数b过滤
#having和where能互换吗?效率谁高?
5 事务 transaction
5.1 概念:
数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
简单的说:事务就是将一堆的SQL语句(通常是增删改操作)绑定在一起执行,要么都执行成功,要么都执行失败,即都执行成功才算成功,否则就会恢复到这堆SQL执行之前的状态。
下面以银行转账为例,A转100块到B的账户,这至少需要两条SQL语句:
- 给A的账户减去100元;
update 账户表 set money=money**-100** where name='A';
- 给B的账户加上100元。
update 账户表 set money=money**+100** where name='B';
如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常,也可能是其他什么原因),那么B的账户没有加上100元,而A却减去了100元,在现实生活中这肯定是不允许的。
如果在转账过程中加入事务,则整个转账过程中执行的所有SQL语句会在一个事务中,而事务中的所有操作,要么全都成功,要么全都失败,不可能存在成功一半的情况。
也就是说给A的账户减去100元如果成功了,那么给B的账户加上100元的操作也必须是成功的;否则,给A减去100元以及给B加上100元都是失败的。
5.2 事务4个特性ACID
一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
- 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中如果发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
5.3 隔离级别
事务隔离分为不同级别,包括
- 读未提交(Read uncommitted) 安全性最差,可能发生并发数据问题,性能最好
- 读提交(read committed) Oracle默认的隔离级别
- 可重复读(repeatable read)MySQL默认的隔离级别,安全性较好,性能一般
- 串行化(Serializable) 表级锁,读写都加锁,效率低下,安全性高,不能并发
5.4 查询mysql的隔离级别
在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要手动开启事务和结束事务。
- 开启事务:start transaction;
- 结束事务:commit(提交事务)或rollback(回滚事务)。
在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务,commit表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。或者rollback,表示回滚,即回滚到事务的起点,之前做的所有操作都被撤消了!
SELECT @@tx_isolation;
Repeatable Read(可重读)
MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。
5.5 事务处理
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
- 事务处理可以用来维护数据的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行
- 事务用来管理 insert、update、delete 语句,因为这些操作才会“破坏”数据,查询select语句是不会的
- MySQL默认数据库的事务是开启的,执行SQL后自动提交。
- MySQL的事务也可以改成手动提交,那就有两个步骤:先开启,写完SQL后,再手动提交。
5.6 提交 commit
多条语句时,批量执行,事务提交
有了事务,多步操作就形成了原子性操作,高并发下也不会引起数据错乱
mysql的事务默认就是开启的 – 多条语句一起操作时,要么一起成功要么一起失败
BEGIN; #关闭事务的自动提交,相当于start transaction
INSERT INTO user (id) VALUES(25);#成功
INSERT INTO user (id) VALUES(5);#已经存在5了,会失败
COMMIT; #手动提交事务
5.7 回滚 rollback
多条语句,批量执行,insert插入重复的主键导致失败时,事务回滚
BEGIN;
INSERT INTO user (id) VALUES(15);
INSERT INTO user (id) VALUES(35);#存在了
ROLLBACK;#事务回滚,就不会再提交了
5.8 测试
MySQL数据库会为每条SQL提供事务管理.每条SQL执行前MySQL会自动开启事务,SQL执行结束MySQL会自动结束事务.
如果想要自己管理事务: 开启事务/结束事务(commit/rollback)
#测试 手动管理事务CUD:模拟向c表中插入数据
START TRANSACTION; #开启事务
INSERT INTO c VALUES(NULL,'654321');
INSERT INTO c VALUES(NULL,'123456');
COMMIT; #结束事务
6 字段约束
字段约束:非空约束,唯一约束,主键约束,默认约束。
6.1 非空约束 not null
DROP TABLE IF EXISTS tb_user; #如果表存在则删除,慎用会丢失数据
CREATE TABLE tb_user(
id INT AUTO_INCREMENT,
NAME VARCHAR(30) UNIQUE NOT NULL,
age INT,
phone VARCHAR(20) UNIQUE NOT NULL,
email VARCHAR(30) UNIQUE NOT NULL,
PRIMARY KEY (id)
);
DESC tb_user;
#id为自增主键,null值无效,数据库会自动用下一个id值替代
#age因为运行为null,所以可以设置为null
INSERT INTO tb_user (id,age) VALUES(NULL,NULL);
6.2 唯一约束 unique
Name字段创建了唯一约束,插入数据时数据库会进行检查,如果插入的值相同,就会检查报错:
DROP TABLE IF EXISTS tb_user; #如果表存在则删除,慎用会丢失数据
CREATE TABLE tb_user(
id INT,
NAME VARCHAR(30) UNIQUE NOT NULL,
phone VARCHAR(20) UNIQUE NOT NULL,
email VARCHAR(30) UNIQUE NOT NULL,
PRIMARY KEY (id)
);
DESC tb_user;
INSERT INTO tb_user (id,NAME) VALUES(1,'tony');
INSERT INTO tb_user (id,NAME) VALUES(2,'tony');
# 执行上面语句出错:
Query : INSERT INTO tb_user (id,NAME) VALUES(2,'tony')
Error Code : 1062
Duplicate entry 'tony' for key 'name'
# 展示表结构:
DESC tb_user;
6.3 主键约束 primary key
主键是一条记录的唯一标识,具有唯一性,不能重复
DROP TABLE IF EXISTS tb_user; #如果表存在则删除,慎用会丢失数据
CREATE TABLE tb_user(
id INT,
NAME VARCHAR(30),
PRIMARY KEY (id)
);
INSERT INTO tb_user (id,NAME) VALUES(1,'tony');
INSERT INTO tb_user (id,NAME) VALUES(1,'hellen');
# 第二句插入就会报错:
Query : INSERT INTO tb_user (id,NAME) VALUES(1,'hellen')
Error Code : 1062
Duplicate entry '1' for key 'PRIMARY'
提示主键1的值已经存在,重复了
6.4 外键约束 foreign key
外键(FK)是用于建立和加强两个表数据之间的链接的一列或多列。通过将保存表中主键值的一列或多列添加到另一个表中,可创建两个表之间的链接。这个列就成为第二个表的外键。
当创建或更改表时可通过定义 FOREIGN KEY 约束来创建外键。
例如,数据库 pubs 中的 titles 表与 publishers 表有链接,因为在书名和出版商之间存在逻辑联系。
titles 表中的 pub_id 列与 publishers 表中的主键列相对应。titles 表中的 pub_id 列是到 publishers 表的外键。
写法:
foreign key(user_id) REFERENCES tb_user(id);
foreign key(当前表的主键名) references 对方表名(对方表的主键);
注意:
子表中的主键的值,必须取自主表
主表中的记录,如果需要删除,必须保证子表中没人在使用,否则会报错
DROP TABLE IF EXISTS tb_user_address; #如果表存在则删除,慎用会丢失数据
DROP TABLE IF EXISTS tb_user; #如果表存在则删除,慎用会丢失数据
CREATE TABLE tb_user (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, #自增主键
NAME VARCHAR(50) NOT NULL UNIQUE, #非空,唯一索引
sex CHAR(2) DEFAULT '男', #默认值
phone CHAR(18),
age INT,
CHECK (age>0 AND age<=200),
);
CREATE TABLE tb_user_address (
user_id INT PRIMARY KEY NOT NULL,
address VARCHAR(200),
foreign key(user_id) REFERENCES tb_user(id)
);
DESC tb_user;
tb_user_address中user_id字段录入tb_user表不存在的主键值,将报错
6.5 默认约束 default
默认值
DROP TABLE IF EXISTS tb_user; #如果表存在则删除,慎用会丢失数据
CREATE TABLE tb_user (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, #自增主键
NAME VARCHAR(50) NOT NULL UNIQUE, #非空,唯一索引
sex CHAR(2) DEFAULT '男', #默认值
phone CHAR(18),
age INT,
createdTime DATE DEFAULT NOW()
);
DESC tb_user;
6.6 检查约束 check
很少使用,了解即可,录入age超过200将报错
DROP TABLE IF EXISTS tb_user; #如果表存在则删除,慎用会丢失数据
CREATE TABLE tb_user (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, #自增主键
NAME VARCHAR(50) NOT NULL UNIQUE, #非空,唯一索引
sex CHAR(2) DEFAULT '男', #默认值
phone CHAR(18),
age INT,
CHECK (age>0 AND age<=200),
createdTime DATE DEFAULT NOW()
);
DESC tb_user;
6.7 测试
#字段约束:非空约束/唯一约束/主键约束/默认约束..
#1.默认约束:给字段使用default添加默认值
CREATE TABLE e(
id INT PRIMARY KEY AUTO_INCREMENT,
sex VARCHAR(10) DEFAULT '男' #默认约束,设置默认值
)
#2.检查约束:给字段使用check添加合法性的检查
CREATE TABLE f(
id INT PRIMARY KEY AUTO_INCREMENT,
age INT,
CHECK(age<100)#检查约束,age录入不合法数据时无法保存
)
#3.外键约束:防止了冗余的数据,通过外键来描述两张表的关系
#特点是:当子表中添加数据时,子表的主键值 必须 取自主表!
#当主表删除数据时,子表没有相关的记录
CREATE TABLE tb_user(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
PASSWORD VARCHAR(20)
)
CREATE TABLE tb_user_addr(
user_id INT PRIMARY KEY,
address VARCHAR(100) ,
#描述和tb_user表的关系,外键
#语法:foreign key(本表的主键名) references 对方表名(对方表的主键)
FOREIGN KEY(user_id) REFERENCES tb_user(id) #创建外键
)
7 总结
7.1 char和varchar有什么区别?
char为定长字符串,char(n),n最大为255
varchar为不定长字符串,varchar(n),n最大长度为65535
char(10)和varchar(10)存储abc,那它们有什么差别呢?
char保存10个字符,abc三个,其它会用空格补齐;而varchar只用abc三个位置。
7.2 datetime和timestamp有什么区别?
数据库字段提供对日期类型的支持,是所有数据类型中最麻烦的一个,慢慢使用就会体会出来。
date 是 年与日
time是 时分秒
datetime年月日时分秒,存储和显示是一样的
timestamp时间戳,存储的不是个日期,而是从1970年1月1日到指定日期的毫秒数
7.3 中文乱码
如果在dos命令下执行insert插入中文数据,数据又乱码,那现在sqlYog客户端执行下面命令:
set names gbk;
设置客户端字符集和服务器端相同。如果不知道它到底用的什么编码?怎么办呢?很简单,两个都尝试下,哪个最后操作完成,查询数据库不乱码,就用哪个。
那为何会造成乱码呢?
Mysql数据库默认字符集是lantin1,也就是以后网页中遇到的ISO8859-1,它是英文字符集,不支持存放中文。我们创建库时,可以指定字符集:
create database yhdb charset utf8;
但这样很容易造成服务器和客户端编码集不同,如服务器端utf8,客户端ISO8859-1。mysql和客户端工具都有习惯的默认编码设置,好几个地方,要都统一才可以保证不乱码。
我们只要保证创建数据库时用utf8,使用可视化工具一般就基本正确。
7.4 注释
- /* 很多注释内容 */
- #行注释内容
- 行注释内容,较常使用
7.5 主键、外键、唯一索引的区别?
- Primary Key 主键约束,自动创建唯一索引
- Foreign Key 外键约束,外键字段的内容是引用另一表的字段内容,不能瞎写
- Unique Index 唯一索引,唯一值但不是主键
7.6 drop、delete和truncate之间的区别?
drop删除库或者表,数据和结构定义
delete和truncate只是删除表的数据
delete可以指定where条件,删除满足条件的记录,tuncate删除所有记录
对于自增字段的表,delete不会自增值清零,而truncate是把表记录和定义都删除了,然后重建表的定义,所以自增主键会重头开始计数