目录
使用SQLyog软件操作数据库
1.所谓安装MySQL数据库,就是在主机安装一个数据库管理系统(DBMS),这个管理程序可以管理多个数据库。DBMS(database manage system)
2.一个数据库可以创建多个表,以保存数据。
3.数据库管理系统(DBMS)、数据库和表的关系如图所示:

表的一行成为一条记录(在Java程序中,一行程序往往使用对象表示),一行中的一列称为一个字段。
DDL:数据定义语句[create 表,库..]
DML:数据库操作语句[增加 insert,修改 update,删除delete]
DQL:数据查询语句[select]
DCL:数据控制语句[管理数据库:比如用户权限 grant revoke]
[这里是可选限制条件]
create database 数据库名 [CHARACTER SET 字符集 [COLLATE 校对规则]]
注意:
名字不能和关键字重名,如果想想重名则可使用反引号(英文输入法,tab键上面,!的左边)包裹名字
例如
create database `database`;
举个例子
# 创建一个使用utf8字符集的cs_db02数据库
CREATE DATABASE cs_db02 CHARACTER SET utf8;
# 创建一个使用utf8字符集,并带校对规则的cs_db03数据库
CREATE DATABASE cs_db03 CHARACTER SET utf8 COLLATE utf8_bin;
# 校对规则 utf8_bin 区分大小写 默认utf8_general_ci 不区分大小写
show databases;
use 数据库名
drop database 数据库名
删库是很危险的操作,所以一般操作时要谨慎使用
删除分为逻辑删除和物理删除,
mysqldump -u 用户名 -p -B 数据库1 数据库2 数据库n > 文件名sql(含路径)
例如:
mysqldump -u root -p -B cs_db01 cs_db03 > d:\\bak.sql
Source 文件名.sql(含路径)

注意decimal类型,如果设置第二个参数为0时可以表示整数
char(4) //这个44表示字符数(最大255),不是字节数,不管中文还是字幕都是放四个,按字符计算。
varchar(4) //这个4表示字符数,不管时字母还是中文都是定义好的表的编码存放数据
共同点:不管是 中文还是英文字母,都是最多存放4个,是按照字符来存放的
char(4)是定长(固定的大小),就是说,即使插入'aa',也会占用分配的4个字符的空间
varchar(4)是边长(变化的大小),就是说,如果插入'aa'实际占用空间大小并不是4个字符,而是按照实际占用空间来分配
特别注意:
varchar本身还需要占用1~3个字节来记录存放内容长度 L(实际数据大小) + (1~3)字节
什么时候使用char,什么时候使用varchar
1.如果数据是定长,推荐使用char,比如md5的密码,邮编,手机号,身份证号码等等
2.如果一个字段的长度是不确定,我们使用varchar,比如留言,文章
查询速度:char > varchar
在存放文本时,也可以使用text数据结构,可以将text列视为varchar列,注意text不能有默认值,大小0~2^16字节
如果希望存放更多字符,可以选择
mediumtext 0~2^24 或者longtext 0~2^32
- 根据存储的实现:可以考虑用 varchar 替代 text,因为 varchar 存储更弹性,存储数据少的话性能更高。
- 如果存储的数据大于 64K,就必须使用到 mediumtext,longtext,因为 varchar 已经存不下了。
- 如果 varchar(255+) 之后,和 text 在存储机制是一样的,性能也相差无几。
- 需要特别注意 varchar(255) 不只是 255byte,实质上有可能占用的更多。
对表操作的前提是进入该数据库,所以操作表前使用use 数据库进入数据库
create table 表名 (
字段名1 类型,
字段名2 类型,
字段名3 类型,
...
);
例如:
创建actor表,包含id和name
- CREATE TABLE actor ( -- 演员表
- id INT,
- name VARCHAR(32)
- );
desc 表名;
drop table 表名;
insert into 表名 [(参数列表)] values(内容) [,(内容),(内容)...];
例如:
insert into actor (id, name) values(1,‘小明’);

解释第5点
字段是否可以为空时创建表的时候定义的,不为空可以在字段名类型后加not null
例如
- create table t1 (
- id int not null
- );
看下面代码
insert into actor values('2', '小李');
代码不会报错,mysql会把字符串解析,如果是数字,直接替换,但是数字不可以解析为字符串。
update 表名 set 修改内容 where 条件;
例如
修改id为1的名字为小王
update actor set name = '小王' where id = 1;
delete from 表名 where 条件;
例如
删除id为1的记录
delete from actor where id = 1;
select 查询内容 from 表名[,表名,表名...] [限制条件];
例如
查询actor所有信息
select * from actor
查询actor的id,name(分别命名为号,姓名)
select 查询的字段名 [as] 别名 from 表名 [限制条件];
select id as '号', name as '姓名' from actor
as可以省略
查询actor的id(去除重复id)
select distinct 查询的字段名 form 表名 [限制条件];
select distinct id from actor;
查询actor的全部信息(升序排列)
select 查询的字段名 from 表名 order by 排列字段 [asc/desc];
select * from actor order by id asc;
比较运算符
| 运算符 | 说明 | ||||||||
| >,>=,<,<= | 大于,大于等于,小于,小于等于 | ||||||||
| = | 等于,NULL不安全,例如NULL = NULL 结果时NULL | ||||||||
| <=> | 等于,NULL安全,例如NULL = NULL 结果时TRUE(1) | ||||||||
| !=,<> | 不等于 | ||||||||
| BETWEEN a0 END a1 | 范围分配,[a0,a1],如果 a0 <= value <= a1,返回TRUE | ||||||||
| IN (option, ...) | 如果是option中任意一个,返回TRUE(1) | ||||||||
| IS NULL | 是NULL | ||||||||
| IS NOT NULL | 不是NULL | ||||||||
| LIKE | 模糊查询,%表示任意多个(包括0个)任意字符; _表示任意一个字符 | ||||||||
逻辑运算符
| 运算符 | 说明 | ||||||||
| AND | 多个条件必须都为TRUE(1),结果才是TRUE(1) | ||||||||
| OR | 任意一个条件为TRUE(1),结果为TRUE(1) | ||||||||
| NOT | 条件为TRUE(1),结果为FALSE(0) | ||||||||
注意:
1. WHERE条件可以使用表达式,但不能使用别名。
2. AND的优先级高于OR,在同时使用时,需要使用小括号()包裹优先执行的部分
count(*);//表示算出所有记录
count(列名1);//表示算出所有列名1不为NULL的总数
l例如
查询actor记录个数
select count(*) as '总记录数' from actor;
sum(统计的列名)
例如
查询actor表的id之和
select sum(id) from actor;
avg(统计的列名)
查询actor表的id平均值
select avg(id) from actor;
例如max(统计的列名)
查询actor表的id最大值
select max(id) from actor;
select 查询字段 from 表名 group by 分组字段;
例如
-- (1)显示每种岗位的雇员总数。平均工资
SELECT COUNT(empno),AVG(sal),job FROM emp GROUP BY job;#正确的



MySQL数据库的用户密码就是PASSWORD函数加密 
select 查询字段 from 表名 限制条件 limit start, rows;
例如
-- 分页查询
-- 按雇员的id号升序取出,每页显示3条记录,请分别显示 第1页,第2页,第2页
- -- 第一页
- SELECT * FROM emp
- ORDER BY empno
- LIMIT 0, 3;
-
- -- 第二页
- SELECT * FROM emp
- ORDER BY empno
- LIMIT 3, 3;
如果select语句同时包含有[where]group by,having,limit,order by 那么他们的顺序是:
[where]group by,having,orderby,limit

-- 思考题:显示公司员工名字和它的上级的名字
- SELECT * FROM emp;
-
- SELECT * FROM emp worker,emp boss;
-
- SELECT worker.ename AS '员工', boss.ename AS '老板'
- FROM emp worker,emp boss
- WHERE worker.`mgr` = boss.`empno`;
-- 自连接的特点
-- 1. 把同一张表当作两张表使用
-- 2. 需要给表去别名 表名 表别名
-- 3. 列名不明确,可以指定列的别名 列名 as 列的别名
单列子查询
例如
请思考:如何显示与SMITH同一部门的所有员工?
/*
1. 先查询到 SMITH的部门号得到
2. 把上面的select 语句当做一个子查询来使用
*/
- SELECT deptno
- FROM emp
- WHERE ename = 'SMITH';
-
-
- SELECT *
- FROM emp
- WHERE deptno = (SELECT deptno
- FROM emp
- WHERE ename = 'SMITH');
查询和部门10的工作相同的雇员的
-- 名字、岗位、工资、部门号,但是不含10自己的信息
/*
1. 查询到10号部门有哪些工作
2. 把上面查询的结果当作子查询使用
*/
- SELECT DISTINCT job
- FROM emp
- WHERE deptno = '20';
-
-
- SELECT ename,job,sal,deptno
- FROM emp
- WHERE job IN (SELECT DISTINCT job
- FROM emp
- WHERE deptno = '10') AND deptno != 10;
多行子查询
如何显示工资比部门30的其中一个员工的工资高的员工的姓名、工资和部门号
常规思路
- SELECT ename,sal,deptno
- FROM emp
- WHERE sal > (SELECT MIN(sal)
- FROM emp
- WHERE deptno = 30);#正确
上述代码其实可以用关键字ANY实现
- SELECT ename,sal,deptno
- FROM emp
- WHERE sal > ANY(SELECT sal
- FROM emp
- WHERE deptno = 30);#正确
还有用关键字ALL实现
- SELECT ename,sal,deptno
- FROM emp
- WHERE sal > ALL(SELECT sal
- FROM emp
- WHERE deptno = 30);#正确
多列子查询
例如
查找每个部门工资高于本部门平均工资的人的资料
- SELECT AVG(sal) AS sal, deptno
- FROM emp
- GROUP BY deptno;
-
- SELECT deptno, AVG(sal) AS sal
- FROM emp
- GROUP BY deptno;
-
- SELECT ename, sal, avg_sal
- FROM emp, (SELECT AVG(sal) AS avg_sal, deptno
- FROM emp
- GROUP BY deptno) temp
- WHERE emp.`deptno` = temp.deptno AND emp.`sal` > temp.avg_sal;
-- 查找每个部门工资最高的人的详细资料
- SELECT MAX(sal), deptno
- FROM emp
- GROUP BY deptno;
-
- SELECT *
- FROM emp
- WHERE (sal, deptno) IN (SELECT MAX(sal) AS sal, deptno
- FROM emp
- GROUP BY deptno)
- ORDER BY sal;#升序
使用临时表
- SELECT emp.`sal`, temp.max_sal, emp.`deptno`
- FROM emp, (SELECT MAX(sal) AS max_sal, deptno
- FROM emp
- GROUP BY deptno) temp
- WHERE emp.sal = temp.max_sal AND emp.`deptno` = temp.deptno;
-- 显示每个部门的信息(包括:部门名,编号,地址)和人员数量
- SELECT dname, dept.deptno, temp.aa AS '人数'
- FROM dept, (SELECT COUNT(*) AS aa, deptno
- FROM emp
- GROUP BY deptno) temp
- WHERE dept.`deptno` = temp.deptno;
-- 还有一种写法 表.* 表示将该表所有列都显示出来,可以简化sql语句
-- 在多表查询中,当多个表的列不重复时,才可以直接写列名
- SELECT dname, temp.*
- FROM dept, (SELECT COUNT(*) AS '人数', deptno
- FROM emp
- GROUP BY deptno) temp
- WHERE dept.`deptno` = temp.deptno;
-- 表的复制
-- 为了对某个ssql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据
表结构相同时
- INSERT INTO my_tab_02
- SELECT * FROM emp;
不同时则需要利用select查询子表赋值
- INSERT INTO my_tab_01
- (id, `name`, sal, job, deptno)
- SELECT empno,ename,sal,job,deptno FROM emp;
- SELECT ename,sal,job FROM emp WHERE sal > 2500;
-
- SELECT ename,sal,job FROM emp WHERE job='MANAGER';
-- union all 就是将两个查询结果合并,不会去重
- SELECT ename,sal,job FROM emp WHERE sal > 2500
- UNION ALL
- SELECT ename,sal,job FROM emp WHERE job='MANAGER';
-- union 就是将两个查询结果合并,会去重
- SELECT ename,sal,job FROM emp WHERE sal > 2500
- UNION
- SELECT ename,sal,job FROM emp WHERE job='MANAGER';
-- 使用左连接
-- (显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)
将两个表联合,找到公共数据
- SELECT `name`,stu.`id`,grade
- FROM stu,exam
- WHERE stu.`id` = exam.`id`;
-- 改成左外连接(如果左表有的数据,右表没有要查询的数据,则置为NULL)
- SELECT `name`,stu.`id`,grade
- FROM stu LEFT JOIN exam
- ON stu.`id` = exam.`id`;
-- 改成右外连接(如果右表有的数据,左表没有要查询的数据,则置为NULL)
- SELECT `name`,stu.`id`,grade
- FROM stu RIGHT JOIN exam
- ON stu.`id` = exam.`id`;
1.primary key不能重复而且不能为null
2.一张表最多只能有一个主键,但可以是复合主键
3.主键的指定方式 有两种
直接在字段后指定:字段名 primary key
在表定义最后写 primary key(列名)
4.使用desc 表名,可以看到primary key的情况
5.实际开发中,每个表往往都会设计一个主键
- CREATE TABLE t17
- (id INT PRIMARY KEY, -- 表示id列是主键
- `name` VARCHAR(32),
- email VARCHAR(32));
-
-
-
- CREATE TABLE t20
- (id INT,
- `name` VARCHAR(32),
- email VARCHAR(32),
- PRIMARY KEY (`name`)
- );
-
-
-
- CREATE TABLE t18
- (id INT,
- `name` VARCHAR(32),
- email VARCHAR(32),
- PRIMARY KEY (id, `name`) -- 这里就是复合主键
- );
和primary key语法一样,有两种定义方式。
1.如果没有指定 not null,则unique字段可以有多个null
2.一张表可以有多个unique字段
foreign key(本表字段名) references 主表名(主键名或unique字段名)
- -- 创建主表 my_class
- CREATE TABLE my_class(
- id INT PRIMARY KEY, -- 班级编号
- `name` VARCHAR(32) NOT NULL DEFAULT '');
-
- -- 创建 从表 my_stu
- CREATE TABLE my_stu(
- id INT PRIMARY KEY, -- 学生编号
- `name` VARCHAR(32) NOT NULL DEFAULT '',
- class_id INT, -- 学生所在班级的编号
- -- 下面指定外键关系
- FOREIGN KEY (class_id) REFERENCES my_class(id) -- 不能使用my_class.id
- );
.1.外键指向的表的字段,要求是primary key 或者是 unique
2.表的类型是innodb,这样的表才支持外键
3.外键字段的类型要和主键字段的类型一致(胀肚可以不同)
4.外键字段的值,必须在主键字段中出现过,或者为null[前提是外键字段允许为null]
5.一旦建鲤主外键的关系,数据不能随意删除了
oracle和sql server均支持check,但是mysql5.7还不支持check,知错语法校验,但不会生效(mysql8生效)
在mysql中实现check的功能,一般是在程序中控制,或者通过触发器完成。
- CREATE TABLE t23 (
- id INT PRIMARY KEY,
- `name` VARCHAR(32),
- sex VARCHAR(6) CHECK (sex IN ('man', 'woman')),
- sal DOUBLE CHECK ( sal > 1000 AND sal < 2000)
- );
字段名 整形 primary key auto_increment
- CREATE TABLE t25
- (id INT PRIMARY KEY AUTO_INCREMENT,
- email VARCHAR(32) NOT NULL DEFAULT '',
- `name` VARCHAR(32) NOT NULL DEFAULT '');

下面是我练习时遇到的问题,以及找的资料:
sql自增长必须是主键吗?
mysql 只有主键能自动增长么 - 小程大序的猿 - 博客园
MySQL自增长可以设置多个吗?
MySQL如何同时自增自减多个字段_咔咔-的博客-CSDN博客_mysql 多个自增字段
索引的优势:查询速度块
底层实现:B+数
代价:
1.磁盘占用
2.对dml语句的效率影响
1.主键索引,主键自动的为主索引(类型Primary key)
2.唯一索引 (UNIQUE)
3.普通索引(INDEX)
4.全文索引(FULLTEXT)[适用于MyISAM]
1.
- CREATE TABLE t26 (
- id INT PRIMARY KEY,
- `name` VARCHAR(32));
2.
- CREATE TABLE t26 (
- id INT,
- `name` VARCHAR(32)),
- PRIMARY KEY (id)
- );
3.
- CREATE TABLE t26 (
- id INT,
- `name` VARCHAR(32)),
- );
-
- ALTER TABLE t26 ADD PRIMARY KEY (id);
- ALTER TABLE t26 ADD PRIMARY KEY id; 错误的
4.
- CREATE TABLE t27 (
- id INT,
- `name` VARCHAR(32));
-
- ALTER TABLE t27 ADD PRIMARY KEY index_id (id);
1.
- CREATE TABLE t25 (
- id INT UNIQUE,
- `name` VARCHAR(32));
2.
- CREATE TABLE t27 (
- id INT,
- `name` VARCHAR(32),
- UNIQUE (id)
- );
3.
- CREATE TABLE t25 (
- id INT,
- `name` VARCHAR(32));
- CREATE UNIQUE INDEX id_index ON t25 (id);
- CREATE UNIQUE INDEX id_index ON t25 id; 错误的
注意
- 一下三种都是不可以的
-
- ALTER TABLE t27 ADD UNIQUE id_index (id);
- ALTER TABLE t27 ADD UNIQUE (id);
- ALTER TABLE t27 ADD UNIQUE id;
1.
- CREATE TABLE t27 (
- id INT,
- `name` VARCHAR(32)
- );
-
- CREATE INDEX id_index ON t27 (id);
2.
ALTER TABLE t27 ADD INDEX id_index (id);
一般情况是很少使用mysql的全文索引,开发中考虑:Solr和ElasticSearch(ES)
1.
- 删除索引
- DROP INDEX id_index ON t27;
2.
- 删除主键索引
- ALTER TABLE t27 DROP PRIMARY KEY;
1.
SHOW INDEX FROM t27;
2.
SHOW INDEXES FROM t27;
3.
SHOW KEYS FROM t27;
4.
- 不全
- DESC t27;
前三种一样的效果

最后一个

先删除索引在添加索引
1.较频繁的作为查询条件字段应该创建索引
2.唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
3.更新非常频繁的字段不适合创建索引
4.不会出现在where子句中字段不该创建索引
什么是事务?
事务用于保证数据的一致性,它由一组相关的dml语句组成,改组的dml语句要么全部成功,要你全部失败(原子性)。
其实游戏中的回档就是事务的一种体现
经典例子:转账
小明要给小李转账100元
这是两个SQL语句,如果小明的语句执行成功,突然服务器崩了,那么小李的钱是没有的,但是小明失去了100元。

如何解救呢?
答案就是使用事务,在转账前开启事务。即初始保存点,如果发生意外返回保存点

- -- 1. 创建一张测试表
- CREATE TABLE t27
- ( id INT,
- `name` VARCHAR(32));
- -- 2. 开始事务
- START TRANSACTION;
- -- 3. 设置保存点
- SAVEPOINT a;
- -- 执行dml 操作
- INSERT INTO t27 VALUES(100, 'tom');
- DELETE FROM t27 WHERE id = 100;
- SELECT * FROM t27;
-
- SAVEPOINT b;
- -- 执行dml操作
- INSERT INTO t27 VALUES(200, 'jack');
-
- SELECT * FROM t27;
-
- -- 回退到 b
- ROLLBACK TO b;
-
- -- 继续回退 a
- ROLLBACK TO a;
- COMMIT;
1.如果不开启事务,默认情况下,dml操作时自动提交的,不能回滚
2.如果开启一个事务,你没有创建保存点,你可以执行rollback,默认就是回退到你事务开始的状态
3.你可以在这个事务中(还没有提交时),创建多个保存点,比如:savepoint aaa;执行dml,savepoint bbb
4.你可以在事务没有提交前,选择回退到哪个保存点
5.mysql的事务机制需要innodb的存储引擎还可以使用,myisam不好使
6.开始一个事务start transaction,set autocommit = off;
1.多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个连接在获取数据时的准确性。(通俗解释)
2.如果不考虑隔离性,可能引发如下问题:
脏读
不可重复度
幻读
当一个事务读取另一个事务尚未提交的修改时,产生脏读
同一查询在同一事务中多次进行,由于其他提交事务所做的修改或者删除,每次返回不同的结果集,此时发生不可重复读
同一查询在同一事务中多次进行,由于其他提交事务所作的插入操作,每次返回不同的结果集,此时发生幻读

- 查看当前会话隔离级别
- SELECT @@tx_isolation;
- 查看系统当前隔离级别
- SELECT @@global.tx_isolation;
- 设置当前会话隔离级别
- SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
- 设置系统当前隔离级别
- SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
设置默认隔离级别



SHOW ENGINES;

InnoDB


1.MyISAM不支持事务、也不支持外键,但其访问速度块,对事务完整性没有要求
2.InnoDB存储引擎提供具有提交、回滚和崩溃恢复能力的事务安全。但是比起MyISAM存储引擎,InnoDB写的处理效率差一下并且会占用更多的磁盘空间以保留数据和索引
3.MEMORY存储引擎使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问速度非常快,因为它的数据是放在内存中的,并且默认使用HASH索引。但是一旦服务关闭,表中的数据就会丢掉,表的结构还在。
ALTER TABLE '表名' ENGINE = '存储引擎名';
1.视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含列,其数据来自对应的真实表(基表)
2.视图和基表的关系

-- 创建一个视图emp_vview01,只能查询emp表的(empno,ename,job和deptno)信息
- CREATE VIEW emp_view01
- AS
- SELECT empno,ename,job,deptno FROM emp;
视图其实还是一张表,表的操作同样适用于视图操作。
创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式:视图名.frm)

视图没有.ibd文件,没有内容


- -- 解读 (1) 'aaa'@'local' 表示用户的完成信息 'cuishuai' 用户名 'localhost' 登录的IP
- -- (2) 123456 密码,但是注意 存放到 mysql.user表时,是password('123456') 加密后的密码
- CREATE USER 'aaa'@'localhost' IDENTIFIED BY '123456';
- SET PASSWORD = PASSWORD('abcdef');
-
-
- -- 修改其他人的密码,需要权限
-
- SET PASSWORD FOR 'aaa'@'localhost' = PASSWORD('123456');
DROP USER 'cuishuai'@'localhost';
-
- -- 给 Powering 分配 查看 news 表和 添加news的权限
- GRANT SELECT,INSERT
- ON testdb.news
- TO 'Powering'@'localhost';
-
-
- GRANT UPDATE
- ON testdb.news
- TO 'Powering'@'localhost';
- - 回收 Powering用户在 testdb.news 表的所有权限
- REVOKE SELECT,UPDATE,INSERT ON testdb.news FROM 'Powering'@'localhost';
- REVOKE ALL ON testdb.news FROM 'Powering'@'localhost';
-- 在创建用户的时候,如果不指定Host,则为%,%表示所有IP都有连接权限
-- create user xxx;
- CREATE USER jack; -- 等价 CREATE USER ‘jack’@‘%’;
-
- SELECT `host`,`user` FROM mysql.user;
-- 你也可以这样指定
-- create user 'xxx'@'192.168.1.%' 表示 xxx用户在 192.168.1.*的ip可以登录mysql
CREATE USER 'tom'@'192.168.%';
-- 在删除用户的时候,如果 host 不是 %,需要明确指定 '用户'@'host值'
- DROP USER jack; -- 默认就是 DROP USER 'jack'@'%'
-
- DROP USER 'tom'@'192.168.%';
最近JDBC也学完了,JDBC绝对是纯干货,我会把学习总结做出来的,我先缓缓,2+4个小时写完文章太肝了.。

