目录
- -- 演示字符串相关函数的使用
- -- charset(str) 返回字符串集合
- SELECT CHARSET (ename) FROM emp;
- -- concat(string2[,....]) 连接字符串 将多个列拼接成一列
- SELECT CONCAT(ename,' 工作是 ',job) FROM emp;
- -- instr (string,substring) 返回substring在 string中出出现的位置,没有返回0
- SELECT INSTR('hanshunping','ping') FROM DUAL;
- -- DUAL 亚元表,系统表 可以作为一个测试表使用
- -- ucase (string2) 转为大写或者小写
- SELECT UCASE(ename) FROM emp; -- 转大写 ucase
- SELECT LCASE(ename)FROM emp; -- 转小写 lcase
- -- LEFT (string2,length) 从string2 的最左边起取length个字符
- SELECT LEFT(ename,2) FROM emp; -- 右边边取 right
- -- length(string) 统计长度 按照字节返回 utf8 一个汉字占三个比比特位
- SELECT LENGTH(ename) FROM emp;
- -- replace (str,search_str,replace_str)
- -- 在str 中replace——str 替换search_str
- SELECT ename,REPLACE(job,'MANAGER','经理') FROM emp;
- -- strcmp (string1,string2) 逐字符比较两字符串大小
- SELECT STRCMP('hsp','hsp') FROM DUAL;
- -- substring(str,position [,length])
- -- 从str的position 开始 从1开始计算,取length 个字符
- SELECT SUBSTRING(ename,1,2) FROM emp; -- 从ename 列的第一个位置开始取出两个字符
- -- ltrim(string2) rtrim (string2) trim trim(string)
- -- 去除前端空格 去除端空格 -- 去除前后空格
- SELECT LTRIM(' han') FROM DUAL;
- SELECT RTRIM('han ') FROM DUAL;
- SELECT TRIM(' han ')FROM DUAL;
-
- SELECT CONCAT(LCASE( SUBSTRING(ename,1,1)),SUBSTRING(ename,2)) AS new_name
- FROM emp;
- SELECT CONCAT(LCASE (LEFT(ename,1)),SUBSTRING(ename,2)) AS new_name
- FROM emp;
-

- -- 演示数学相关函数
-
- -- ABS(num) 绝对值
- SELECT ABS(-1) FROM DUAL;
- -- BIN (decimal_number) 十进制转二进制
- SELECT BIN(23) FROM DUAL;
- -- CEILING (number2) 向上取整 得到比number2 大的最小整数
- SELECT CEILING (33.3) FROM DUAL;
- -- CONV(number2,from_base,to_base) 进制转换
- SELECT CONV(123,10,2) FROM DUAL;
- -- FLOOR (number2) 向下取整 得到比num2 小的最大整数
- SELECT FLOOR (12.5) FROM DUAL;
-
- -- FORMAT (number,decimal_places) 保留小数位 四舍五入
- SELECT FORMAT(12.32,3) FROM DUAL;
-
- -- HEX (DecimalNUmber) 转换为十六进制
- SELECT HEX(123) FROM DUAL;
- -- LEAST (num1,num2 ..... num)
- SELECT LEAST(12,14,12,14,12,11) FROM DUAL;
- -- mod (numerator,denominator) 求余
- SELECT MOD(10,3) FROM DUAL;
- -- rand ([seed]) rand ([seed)] 返回其范围为0<= v <= 1.0
- -- 如果seed 不变,该随机数也不变
- SELECT RAND(3) FROM DUAL;

- -- 日期时间相关函数
- -- CURRENT_DATE() 当前日期
- SELECT CURRENT_DATE() FROM DUAL;
- -- CURRENT_TIME() 当前时间
- SELECT CURRENT_TIME() FROM DUAL;
- -- CURRENT_TIMESTAMP() 当前时间戳
- SELECT CURRENT_TIMESTAMP() FROM DUAL;
-
- -- 创建测试表 信息表
- CREATE TABLE mes (id INT,content VARCHAR(30),send_time DATETIME);
-
- -- 添加一条记录
- INSERT INTO mes
- VALUES(1,'北京新闻',CURRENT_TIMESTAMP());
- SELECT * FROM MES;
-
-

- SELECT id ,content, DATE(send_time)
- FROM mes;
- -- 请查询在十分钟内发布的新闻
- SELECT * FROM mes
- WHERE DATE_ADD(send_time,INTERVAL 10 MINUTE) >= NOW();
- SELECT * FROM mes
- WHERE DATE_SUB(NOW(),INTERVAL 10 MINUTE) <= send_time;
- -- 请在MySQL语句的sql 语句中求出 2011-11-11 和 1990 - 1- 1 相差多少天
- SELECT DATEDIFF('2011-11-11','1990-1-1')/365
- FROM DUAL;
- -- 用mysql 的sql 求出你活了多少天
- SELECT DATEDIFF (NOW(),'1999-11-11') AS new_date FROM DUAL;
- -- 如果你能活80岁,求出你能活多少天
- SELECT DATEDIFF(DATE_ADD('1986-11-11',INTERVAL 80 YEAR),NOW()) AS new_date FROM DUAL;
细节说明:
1.DATE_ADD() 中的 interval 后面可以是 year minute second day 等
2.DATE_SUB() 中的 interval 后面可以是 year minute second hiur day 等
3.DATEDIFF(date1,date2) 得到的是天数,而且是 date1- date2 的天数 因此可以取负数
4.这四个函数的日期类型可以是date datetime 或者 timestamp
- -- YEAR|Month|DAY| DATE(datetime);
- SELECT NOW() FROM DUAL;
- SELECT MONTH(NOW())FROM DUAL;
- SELECT DAY(NOW())FROM DUAL;
- SELECT YEAR('2013-10-10') FROM DUAL;
- -- unix_timestamp(); 返回的是1970—1-1 到 现在的毫秒数
- SELECT UNIX_TIMESTAMP()/(365*24*3600) FROM DUAL;
- -- FROM_UNIXTIME() 时间戳 可以把一个unix 的秒数转换为一个指定格式的日期
- -- 意义 在开发中 可以存放一个整数 然后表示 时间 通过 FROM_UNIXTIME() 来转换
- --
- SELECT FROM_UNIXTIME(1618483484,'%Y-%m-%d %H:%i:%s') FROM DUAL;
四. 加密和系统函数 pwd.sql

- -- 演示加密函数和系统函数
- -- user() 查询用户
- -- 可以查看登录到mysql 的有那些用户,以及登录的ip
- SELECT USER() FROM DUAL; -- 用户 @IP 地址
- -- DATABASE() 数据库名称
- SELECT DATABASE() FROM DUAL;
- SELECT DATABASE();
- -- MD5(str) 为字符串算出一个 MD5 32 的字符串,常用(用户密码)加密
- -- root 密码是 tian - > 加密md5 ——> 在数据库中存放的是加密后的密码
- SELECT MD5('tian') FROM DUAL;
- SELECT LENGTH(MD5('tian')) FROM DUAL;
-
- -- 演示用户表 存放密码的时,是MD5
- CREATE TABLE users1
- (id INT,
- `name` VARCHAR(32) NOT NULL DEFAULT '',
- pwd CHAR(32) NOT NULL DEFAULT '');
- INSERT INTO users1
- VALUES( 100,'tian',MD5('tian'));
- SELECT * FROM users1;
- SELECT *
- FROM users1
- WHERE `name` = 'tian' AND pwd = MD5('tian');
- -- pASSWORD(str) -- 加密 在MySQL 数据库 的用户密码是用 password 函数加密
-
- SELECT PASSWORD('tian') FROM DUAL;
-
- -- select * from mysql.user \G 从原文密码str 计算并返回密码字符串
- -- 通常用于对 mysql 数据库的用户密码加密
- -- mysql.user 表示 数据库.表的含义
- SELECT * FROM mysql.user;

- -- 演示流程控制语句
- -- IF(expr1,expr2,expr3) 如果expr1为true 则返回 expr2 否则返回 expr3
- SELECT IF(TRUE,'北京','上海') FROM DUAL;
-
- -- IFNULL(expr1,expr2) 如果expr1 不为空nuLL 则返回expr1 否则返回expr2
- SELECT IFNULL(NULL,'hsp') FROM DUAL;
- SELECT IFNULL ('jack','hsp') FROM DUAL;
-
- -- select case when expr1 then expr2
- -- when expr3 then expr4 else expr5 end; [类似多重分支]
- -- 如果expr1 为true 则返回 expr2 如果 expr2 为 true 则返回expr4 否则返回 expr5
-
-
- SELECT CASE
- WHEN TRUE THEN 'jack'
- WHEN FALSE THEN 'tom'
- ELSE 'mary' END;
-
- -- 查询 emp 表 如果 comm 是 null 则显示 0.0
- -- 判断是否为空用 is null is not null
- SELECT ename ,IF(comm IS NULL,0.0,comm)
- FROM emp;
- SELECT ename,IFNULL(comm,0.0)
- FROM emp;
- -- 如果 emp 表的job 是 CLERK 则显示 职员 如果是 MANAGER 则显示经理
- -- 如果是 selesman 则显示 销售人员 其他正常显示
- SELECT ename,(SELECT CASE
- WHEN job = 'CLERK' THEN '职员'
- WHEN job = 'MANAGER' THEN '经理'
- ELSE job END)
- FROM emp;
五.MySQL 表查询—— 加强
- -- 查询加强
- -- 使用 where 字句 查询1992.1.1 后入职的员工
- -- 在MySQL中日期类型可以直接比较
- SELECT * FROM emp
- WHERE hiredate > '1992-1-1';
- -- 模糊查询 like操作符
- -- % : 表示0到多个任意字符 _: 表示单个字符
- -- 如何显示首个字符为s 的员工姓名和工资
-
- SELECT ename,sal
- FROM emp
- WHERE ename LIKE 'S%';
- -- 如何显示第三个字符为大写O 的所有员工的姓名和工资
- SELECT ename,sal FROM emp
- WHERE ename LIKE '__O%';
- -- 如何查询没有上级的雇员的情况
- SELECT * FROM emp
- WHERE mgr IS NULL;
- -- 查询表的结构
- DESC emp;
- -- 使用 order by 子句
- -- 如何按照工资的从低到高的顺序,显示雇员的信息 ASC升序
- SELECT * FROM emp
- ORDER BY sal ASC;
- -- 按照部门号升序而员工的工资降序排列 显示雇员信息
- SELECT * FROM emp
- ORDER BY deptno ASC, sal DESC;
- -- 分页 查询
- -- 按照雇员的id号升序取出,每页显示三条记录,请分别显示 第一页 第二页 第三页
- -- 第一页
- SELECT * FROM emp
- ORDER BY empno
- LIMIT 0,3;
- SELECT * FROM emp
- ORDER BY empno
- LIMIT 3,3;
- SELECT * FROM emp
- ORDER BY empno
- LIMIT 6,3;
- SELECT * FROM emp
- ORDER BY empno
- LIMIT 9,3;
-
- -- 推到一个公式
- SELECT * FROM emp
- ORDER BY empno
- LIMIT 每页显示记录数* (第几页 -1) ,每页显示记录数
- SELECT * FROM emp
- ORDER BY empno DESC
- LIMIT 10,5;
- SELECT * FROM emp
- ORDER BY empno DESC
- LIMIT 20,5;
- -- 演示 group by 分组字句
- -- 显示每种岗位的雇员总数,平均工资
- SELECT COUNT(*),AVG(sal),job
- FROM emp
- GROUP BY job;
- -- 显示雇员总数,以及获得补助的雇员数
- -- 获得补助的雇员数 就是 comm 列为非空的 null
- -- count 统计的时候 如果该列的值为null 是不会统计的
- SELECT COUNT(*),COUNT(comm)
- FROM emp;
- -- 统计经理有多少人
- SELECT COUNT(*),COUNT(IF(comm IS NULL,NULL))
- FROM emp;
- -- 统计没有获得补助的雇员数
- SELECT COUNT(*),COUNT(IF(comm IS NULL,1,NULL))
- FROM emp;
- SELECT COUNT(*),COUNT(*) - COUNT(comm)
- FROM emp;
- -- 显示管理者的总人数
- SELECT COUNT(mgr) FROM emp;
- SELECT COUNT(DISTINCT mgr) FROM emp;
- -- 显示雇员工资的最大差值
- -- max() - min()
- SELECT MAX(sal) - MIN(sal) FROM emp;
- SELECT * FROM emp;
如果 select 语句同时包含有 group by, having by ,limit, order by 那么他们的顺序是 group by , having,order by ,limit
- SELECT cloumn1,cloumn2,cloumn3... FROM TABLE
- GROUP BY cloumn 分组
- HAVING CONDITION 过滤
- ORDER BY COLUMN 排序
- LIMIT START,ROWS 分页
- -- 案例 请统计各个group by 部门的平均工资,
- -- 并且是大于1000的 并且按照平均工资从高到底排序 order by
- -- 取出前两行记录 limit
- SELECT deptno, AVG(sal) AS avg_sal
- FROM emp
- GROUP BY deptno
- HAVING avg_sal > 1000
- ORDER BY avg_sal DESC
- LIMIT 0,2;
所谓多表查询是指基于两个和两个以上得表查询。在实际开应用中,查询单个表可能不能满足你得需求(如下面得课程练习) 需要使用到(dept表和emp表)
在默认情况下:当两表查询时,规则
- -- 多表查询
- -- 显示雇员名看,雇员工资以及所在部门的名字【笛卡尔积]
- -- 1.雇员名,雇员工资 来自 emp 表
- -- 2.部门的名称 来自 dept表
- -- 3.需要对 emp 和 dept 表进行查询
- -- 4.当我们需要指定显示某个表的列是,需要 表.列名
-
- SELECT ename,sal,dname
- FROM emp,dept
- WHERE emp.deptno = dept.deptno;
- -- 如和显示部门号为10的部门名,员工名,和工资
- SELECT ename,dname,sal
- FROM emp,dept
- WHERE emp.deptno = dept.deptno AND emp.deptno = 10;
- -- 显示各个员工的姓名,工资,及其工资级别
- -- 思路 姓名 工资 及其 工资级别 来自 emp
- -- 工资级别 salgrade
- -- 写sql 先写一个简单的 然后加上固定条件
-
- SELECT ename, sal,grade
- FROM emp , salgrade
- WHERE sal BETWEEN losal AND hisal;
自连接是指在同一张表的连接查询【将同一张表看作两张表】self.sql
- -- 多表查询的 自连接
- -- 显示公司员工和他的上级的名字
- -- 员工的名字在emp 表 上级的名字 也在emp 表
- -- 员工和上级是通过 emp 表的 mgr 列 关联
- -- 自连接 特点
- -- 把同一张表当作两张表使用
- -- 需要给表取别名 表名 表的别名 不需要AS AS 是给列区取别名的时候使用
- -- 如果列明名不明确 可以指定列的别名 列名 AS 列的别名
-
- SELECT worker.ename AS '职员',boss.ename AS'上级'
- FROM emp worker,emp boss -- 169 13*13
- WHERE worker.mgr = boss.empno;
子查询是指嵌入在其他sql 中的select 语句,也叫嵌套查询
- -- 子查询的演示
- -- 如何显示与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. 十号部门有那些工作岗位
- -- 2. 把上面查询的结果当作子查询使用
- SELECT DISTINCT job -- distinct 去重
- FROM emp
- WHERE deptno = 10;
-
- SELECT ename,job,sal,deptno
- FROM emp
- WHERE job IN (
- SELECT DISTINCT job
- FROM emp
- WHERE deptno = 10
- ) AND deptno != 10
- -- 在 MySQL 中 判断两个指是否相等 使用 =
- -- != <> 这两个都是不等
-
- -- 查询ecshop 中各个类别中,价格最高的商品
- -- 查询 商品表
- -- 先得到 各个类别中,价格最高的商品 max + group by cat_id
- SELECT cat_id,MAX(shop_price)
- FROM ecs_goods
- GROUP BY cat_id;
- SELECT goods_id,cat_id,goods_name,shop_price
- FROM ecs_goods;
-
- SELECT goods_id,ecs_goods.cat_id,goods_name,shop_price
- FROM (
- SELECT cat_id,MAX(shop_price) AS max_price
- FROM ecs_goods
- GROUP BY cat_id
- ) temp,ecs_goods
- WHERE temp.cat_id = ecs_goods.cat_id
- AND temp.max_price = ecs_goods.shop_price;
- -- 把子查询当作一张零时表可以解决很多复杂的查询
在多行子查询中使用all 操作符 allany.sql
- -- 如何显示工资比部门30多的所有员工的工资高的员工的姓名 工资 部门号
- -- all 和 any 的使用
- SELECT ename,sal,deptno
- FROM emp
- WHERE sal > ALL (
- SELECT sal
- FROM emp
- WHERE deptno = 30
- )
- -- 可以 这样写
- SELECT ename,sal,deptno
- FROM emp
- WHERE sal > (
- SELECT MAX(sal)
- FROM emp
- WHERE deptno = 30
- )
在多行子查询中使用any 操作符
- -- 如何显示工资比部门30 的其中一个员工的工资高的员工的姓名 年龄 工资和 部门号
- SELECT ename,sal,deptno
- FROM emp
- WHERE sal > ANY(
- SELECT sal
- FROM emp
- WHERE deptno = 30);
- -- 或者
- SELECT ename,sal,deptno
- FROM emp
- WHERE sal > (
- SELECT MIN(sal)
- FROM emp
- WHERE deptno = 30);
多列子查询 manycolumn.sql
多列子查序则是指查询返回多个列数据的子查询语句
(字段1,字段2 ...) = (select 字段1,字段2 from ...)
- -- 如何查询与smith的部门和岗位完全相同的所有雇员(并且不含smith本人)
- -- 多列 子查询
- -- 分析 1.要得到 smith 部门和岗位
- SELECT deptno,job
- FROM emp
- WHERE ename = 'SMITH';
- -- 2.把上面的查询当作一个子查询来使用并且使用多列子查询的语法进行匹配
- SELECT *
- FROM emp
- WHERE (deptno,job) = (
- SELECT deptno,job
- FROM emp
- WHERE ename = 'SMITH'
- ) AND ename != 'SMITH';
- -- 如何查询与allen 部门和岗位完全相同的所有雇员
- SELECT *
- FROM emp
- WHERE(deptno,job) = (
- SELECT deptno,job
- FROM emp
- WHERE ename = 'ALLEN'
- ) AND ename != 'ALLEN';
-
- SELECT * FROM student;
- -- 查询与松江数学 英语 语文 成绩相同的学生
- SELECT *
- FROM student
- WHERE (chinese,english,math) = (
- SELECT chinese,english,math
- FROM student
- WHERE `name` = '张飞'
- );
自我复制数据(蠕虫复制)
有时,为类对某个sql 语句进行效率测试,我们需要海量数据时,可以使用此方法为表创建海量数据。copytab.sql
- -- 表的复制
- CREATE TABLE my_tab01
- ( id INT,
- `name` VARCHAR(32),
- sal DOUBLE,
- job VARCHAR(32),
- deptno INT);
- DROP TABLE my_tab01;
- DESC my_tab01;
- -- 如何自我复制
- -- 1.先把emp 表的记录复制到 my_tab01
- INSERT INTO my_tab01
- (id,`name`,sal,job,deptno)
- SELECT empno,ename,sal,job,deptno
- FROM emp;
- SELECT * FROM my_tab01;
- -- 2.自我复制
- INSERT INTO my_tab01
- SELECT * FROM my_tab01;
- -- 如何删除一张表中重复的记录
- -- 1.先创建一张表
- -- 2.有重复的记录
-
- CREATE TABLE my_tab02 LIKE emp; -- 把emp表的结构列 复制到my_tab02
- DESC my_tab02;
- INSERT INTO my_tab02
- SELECT * FROM emp;
- -- 考虑去掉重复的
- -- 思路: 1.先创建一张零时表 my_tmp 该表的结构和my_tab02 相同
- -- 2. 把my_tab 的记录 通过distinct 关键字处理后,把记录复制到my_tmp
- -- 3. 清除掉 my_tab02 记录
- -- 4.把 my_tmp 表的记录复制到 my_tab02
- -- 5. drop 掉 my_tmp
- SELECT * FROM my_tab02;
- CREATE TABLE my_tmp LIKE my_tab02;
- INSERT INTO my_tmp
- SELECT DISTINCT * FROM my_tab02;
- DELETE FROM my_tab02;
- INSERT INTO my_tab02
- SELECT * FROM my_tmp;
- DROP TABLE my_tmp;
- SELECT * FROM my_tmp;
有时在实际运用中,为了合并多个select语句的结果,可以使用集合操作符号 union, union all
1. union all
该操作符用于取得两结果相同的并集。当使用该操作符时,不会取消重复行
2.union
该操作符 与union all 相似 但是会自动去掉集中重复行
- -- 合并查询
- 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'; -- 三条
-
- SELECT ename,sal,job
- FROM emp
- WHERE sal > 2500 -- 五条
- UNION
- SELECT ename,sal,job
- FROM emp
- WHERE job = 'MANAGER';
1.前面的查询,时利用where子句对两张表或者多张表,形成的笛卡尔积进行筛选,根据相关条件,显示所有匹配的记录,匹配不上则不显示
2.左外连接 (如果左侧表的表完全显示我们就说是左外连接)
基本语法 select ... from 表1 left join 表2 on 条件
3.右外连接 (如果右侧的表完全显示我们就说是右外连接)
基本语法 select ... from 表1 right join 表2 on 条件
- -- 外连接
- -- 列出部门名称和员工名称和工作,同时要求 显示那些没有员工的部门
- SELECT dname,ename,job
- FROM emp,dept
- WHERE emp.deptno = dept.deptno
- ORDER BY dname;
-
- -- 创建 stu
- CREATE TABLE stu
- ( id INT,
- `name` VARCHAR(32)
- );
- INSERT INTO stu
- VALUES( 1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');
- SELECT * FROM stu;
-
- -- 创建 exam
- CREATE TABLE exam(
- id INT,
- grade INT);
- INSERT INTO exam
- VALUES(1,56),(2,76),(11,8);
- SELECT * FROM exam;
- -- 使用左连接(显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)
- SELECT `name`,stu.id,grade
- FROM stu,exam
- WHERE stu.id = exam.id;
- -- 改成左外连接
- SELECT `name`,stu.id,grade
- FROM stu LEFT JOIN exam
- ON stu.id = exam.id;
- -- 右外连接 显示所有的成绩 如果没有名字匹配显示为空
- SELECT `name`,stu.id,grade
- FROM stu RIGHT JOIN exam
- ON stu.id = exam.id;
小结: 在实际开发中绝大多数情况下 使用的是内连接
约束用于确保数据库的数据满足特定的商业规划
在MySQL中,约束包括:not null, unique,primary key,foreign key 和check 五种
primary key(主键) - 基本使用 字段名 字段名称 primary key 用于位于的表行的数据,当定义主键约束后,该列不能重复
主键的细节:
- -- 主键的使用
- -- id 那么 email
- CREATE TABLE t17
- (id INT PRIMARY KEY, -- 主键 id 添加不可重复
- `name` VARCHAR(32),
- email VARCHAR(32));
- INSERT INTO t17
- VALUES(1,'jack','kkkkk.com'),
- (2,'tom','kkkkk.com');
- SELECT * FROM t17;
- INSERT INTO t17
- VALUES(1,'hsp','kkkkk.com'); -- id 为主键 报错
-
- -- 主键使用的细节讨论
- -- primary key 不能重复而且不能为null
- -- 一张表最多只能有一个主键,但可以是复合主键
- -- 将id 和 name 合并成一个 复合主键
- CREATE TABLE t19
- (id INT, -- 主键 id 添加不可重复
- `name` VARCHAR(32),
- email VARCHAR(32),
- PRIMARY KEY (id,`name`) -- 复合主键 只有这两个都不相同的时候添加不了
- );
- -- 主键的指定方式 有两种
- -- 直接写在字段名后指定 : 字段名 primakry key
- -- 在表定义最后写 primary key (列名)
- -- (在列后面直接指定,列写完后 统一指定,primary key
-
- -- 使用 desc 表名,可以看到 primary key 的情况
- DESC t20 -- 查看t20 的结果 显示约束情况
-
not null(非空)
如果在列上定义了 not null 那么当插入数据时,必须为列提供数据
字段名 字段类型 not null
unique (唯一)
当定义了唯一约束后,该列值时不能重复的
字段名 字段类型 unique
unique 使用细节
1.如果没有指定not null 则 unique 字段可以有多个 null,如果一个字段(列) 是 unique not null 使用效果 类似 primary key
2. 一张表可以有多个unique 字段
foreign key (外键)
用于定义主表和从表之间的关系:外加按约束要定义在从从表上,主表则必须具有之间的约束或是unique 约束,当定义外键约束后,要求外键列数据必须在主表的主键列存在或者是为 null(学生/班级)
FOREIGN KEY (本表字段名) REFERENCES
主表名 (主键名 或 unique 字段名)
- -- 外键演示
- -- 建主表 班级表 myclass
- CREATE TABLE myclass
- ( 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 myclass(id));
- -- 测试数据
- INSERT INTO myclass
- VALUES(100,'java'),(200,'web');
- SELECT * FROM myclass;
- INSERT INTO my_stu
- VALUES(1,'tom',100);
- INSERT INTO my_stu
- VALUES(2,'hsp',300) -- 这里会失败 300 号班级不存在
foreign key (外键) 细节说明
check
用于 强制行数据必须满足的条件,假设在sal 列上定义了check 约束,并要求sal列在1000~2000 之间就会显示错误
oracle 和SQL server 均支持check,但是mysql5.7目前还不支持check,只做语法校验,但不会生效。
- -- check 的使用
- -- 5.7 目前不支持check 只做语法校验,但不会生效
- -- Oracle ,sql server 这两个数据库生效
- -- 测试
- CREATE TABLE t23(
- id INT PRIMARY KEY,
- `nane` VARCHAR(32),
- sex VARCHAR(6) CHECK (sex IN ('man','woman')),
- sal DOUBLE CHECK (sal > 1000 AND sal < 2000));
- INSERT INTO t23
- VALUES (1,'jack','mid',1);
- SELECT * FROM t23;
在某张表中,存在一个id列(整数) 我们希望在添加记录 的时候,该列从1开始,自动增长 increment.sql
字段名 整形 primary key aut_increment
- -- 自增长的使用
- -- 创建表
- create table t24
- ( id int primary key auto_increment,
- email varchar(32) not null default '',
- `name` varchar(32) NOT NULL DEFAULT '');
- DESC T24;
- -- 自增长的使用
- insert into t24
- values (null,'jack@qq.com','jack');
- insert into t24
- values (null,'tom@qq.com','tom');
-
- insert into t24
- (email,`name`) values ('hsp@qq.com','hsp');
- select * from t24;
自增长的细节
为了提高数据库性能,索引是物美价廉的东西,不用加内存,不用该程序,不用调sql,查询速度就可能提高百倍千倍。CREATE INDEX empno_index ON emp (empno) // 创建索引
索引的原理
索引的原理是通过建立索引来提高检索效率的一种方法。在信息检索领域,索引是指按照一定规则对信息进行分类和排序,以便于用户快速定位所需信息的一种数据结构。
MySQL中有三种类型的索引:B-Tree索引、哈希索引和全文索引。其中,B-Tree索引是最常用的一种,也是MySQL中默认的索引类型。B-Tree索引是基于B-Tree算法实现的,它将数据表中的每个值都存储在一个B-Tree中,并通过指针将它们链接起来。当我们执行查询时,MySQL会使用这些指针来快速定位到所需的数据。
索引的代价
- -- 演示MySQL的索引使用
- CREATE TABLE t26(
- id INT,
- `name` VARCHAR(32));
- -- 查询表是否有索引
- SHOW INDEXES FROM t26;
- -- 添加索引
- -- 添加唯一索引
- CREATE UNIQUE INDEX id_index ON t26 (id);
-
- -- 添加普通索引
- CREATE INDEX id_index ON t26 (id);
- -- 如和选择索引
- -- 如果某列的值不重复 则优先使用unique 速度快 否则使用普通索引
- -- 添加 普通索引方式2
- CREATE TABLE t26 ADD INDEX id_index (id);
- -- 添加组件索引 创建表的时候直接添加主键 primary key 或者
- ALTER TABLE t26 ADD PRIMARY KEY (id);
-
-
- -- 删除索引
- DROP INDEX id_index ON t26;
- SHOW INDEX FROM t26;
-
- -- 删除主键索引
- ALTER TABLE t26 DROP PRIMARY KEY;
-
-
- -- 修改索引 先删除在添加新的索引
- -- 查询索引 三种方式
- -- 1
- SHOW INDEX FROM t25;
- -- 第二中方式
- SHOW INDEXES FROM t25;
- -- 方式三
- SHOW KEYS FROM t25;
- -- 方式 4
- DESC t25; -- 信息没有前面三种方式详细
小结: 那些列上适合使用索引
什么时事务
事务用于保证数据的一致性,它是由一组相关的dml语句组成,该组的dml 语句要么全部成功,要么全部失败。如:转账就要用事务来处理,用以保证数据的一致性
事务和锁
当执行事务操作时(dml)语句,MySQL会在表上加锁,防止其他用户该表的数据,这是对用户来讲时非常重要的
回退事务
保存点(savepoint) 保存点是事务中的点,用于取消部分事务,当事务结束时(commit),会自动的删除该事务所有定义的节点。当执行回退事务时,通过指定保存的点
提交事务
使用commit语句可以提交事务,当执行了commit语句后,会确认事务的变换,结束事务,删除保存点,释放锁,数据生效。当使用commit语句结束了事务之后,其他会话将可以查看到事务变话【其他连接】后的新数据【所有的数据都正式生效】
MySQL 事务细节讨论 transcation_detail.sql
- -- 事务几个重要的概念和操作
- -- 1.创建一张测试表
- CREATE TABLE t27 (
- id INT,
- `name` VARCHAR(32));
- -- 开始一个事务
- START TRANSACTION;
- -- 设置一个保存点
- SAVEPOINT a;
- -- 执行dml操作
- INSERT INTO t27
- VALUES (100,'tom');
-
-
- SAVEPOINT b;
- -- 执行 dml 操作
- INSERT INTO t27
- VALUES(200,'jack');
-
- -- 回退到 b
- ROLLBACK TO b;
- -- 回退到 a
- ROLLBACK TO a;
- SELECT * FROM t27;
-
- -- 如果这样,表示直接回退事务开始的状态
- ROLLBACK,
- -- commit 提交事务 一旦执行了commit 在rollback 无法回退
- COMMIT;
十二.mysql 的事务隔离级别
事务隔离级别介绍
事务隔离级别 概念:mysql 隔离级别定义可事务与事务之间的隔离程度

MySQL事务隔离级别
MySQL事务ACID
事务的acid特性
十二.MySQL 表类型和存储引擎

细节说明:
这里介绍三种:MyISAM,innoDB,MEMORY
- -- 表类型和存储引擎
- -- 查看说有的存储引擎
- SHOW ENGINES;
- -- innodb 存储引擎前面使用过了 支持事物和外键 支持行级锁
- -- myisam
- CREATE TABLE t28 (
- id INT,
- `name` VARCHAR(32))ENGINE MYISAM;
- -- 添加速度快 不支持外键和索引 支持表级锁
- START TRANSACTION;
- SAVEPOINT t1;
- INSERT INTO t28 VALUES(1,'jack');
- ROLLBACK TO t1; -- 不支持回滚
- SELECT * FROM t28;
-
- -- memory 存储引擎 数据是存储在内存当作的执行速度非常快(在内存中没有 io 读写) 默认支持索引(hash表)
- CREATE TABLE t29(
- id INT,
- `name` VARCHAR(32)) ENGINE MEMORY;
- INSERT INTO t29
- VALUES(1,'tom'),(2,'jack'),(3,'hsp');
- -- 如果 关闭MySQL 服务,数据丢失,但是表结构还在
- SELECT * FROM t29;
如何选择表的存储引擎
修改存储引擎
ALTER TABLE `表名` ENGINE = 存储引擎;
视图,比如说看emp表的列信息很多,有些信息是个人重要信息(比如:sal,comm,mgr,hiredate) 如果我们希望某个用户只能查询emp表的(empno,ename,job和deptno)信息 可以使用视图
视图的基本概念:视图是一个虚拟表,其内容由查询定义,同真实的表一样,视图包含列,其数据来自对应得真实表(基表)
视图的总结:
视图的基本使用:
视图的细节讨论
- -- 视图的使用
- -- 创建一个视图emp_view01 只能查询emp 表的 empno ename job deptno 信息
- CREATE VIEW emp_view01
- AS
- SELECT empno,ename,job,deptno FROM emp;
- DESC emp_view01;
- SELECT empno,job FROM emp_view01;
-
-
- -- 查看创建视图的指令
- SHOW CREATE VIEW emp_view01;
- -- 删除视图
- DROP VIEW emp_view01;
- -- 视图的细节
- -- 创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式:视图名.frm)
- -- 视图的数据变换会形象到基表,基表的数据变化也会影响到视图[insert update delete]
- -- 修改视图
- UPDATE emp_view01
- SET job = 'MANAGER'
- WHERE empno = 7369;
- SELECT * FROM emp; -- 查询基表
-
- -- 修改视图会影响到基表
- SELECT * FROM emp_view01;
- -- 修改基表也会影响到基表
- UPDATE emp
- SET job = 'SALESAN'
- WHERE empno = 7369;
- -- 视图中可以再使用视图
- DESC emp_view01;
- -- 从emp_view01 当中选出两列 no 和 ename 做出新视图
- CREATE VIEW emp_view02
- AS
- SELECT empno,ename
- FROM emp_view01;
- SELECT * FROM emp_view02;
视图最佳实践
MySQL用户
MySQL中的用户,存储在系统数据库mysql中user 表中
其中user表的重要字段说明:
创建用户
create user ‘用户名’ @ ‘允许登录的位置’ inentified by '密码'
说明:创建用户,同时指定密码
删除用户
drop user '用户名' @ 允许登录的位置;
用户修改密码
修改自己的密码: set password = password('密码');
修改他人的密码: (需要修改权限):
set password for '用户名' @ '登录位置' = password('密码');
MySQL中的权限
给用户授权
基本语法:
grant 权限列表 on 库.对象名 to '用户名' @ '登录位置' 【identified by '密码'】
说明:
回收用户权限
基本语法: revoke 权限列表 on 库.对象名 from '用户名' @ ''登录位置'';
权限生效指令
如果权限没有生成,可以执行下面指令。
基本语法:
FLUSH PRIVILEGES;
- -- 演示用户权限的管理
- -- 创建一个用户(你的你的名字 tian 密码 123
- CREATE USER 'diandian' @'localhost' IDENTIFIED BY '123';
- -- 使用root 用户创建 testdb 表 news
- CREATE DATABASE testdb;
- CREATE TABLE news(
- id INT,
- content VARCHAR(32));
- INSERT INTO
- news
- VALUES (100,'北京新闻');
- SELECT * FROM news;
-
- -- 给diandain 用户分配查看news表 和 添加 news 的权限
- GRANT SELECT,INSERT
- ON testdb.news
- TO 'diandian' @'localhost';
- -- 增加权限
- GRANT UPDATE
- ON testdb.news
- TO 'diandian' @'localhost';
- -- 修改密码为123
- SET PASSWORD FOR 'diandian'@'localhost' = PASSWORD('abc');
- -- 回收 diandian 用户 testdb.news 表的所有权限
- REVOKE SELECT ,UPDATE,INSERT ON testdb.news FROM 'diandian'@'localhost';
- -- 或者
- REVOKE ALL ON testdb.news FROM 'diandian'@'localhost'
- -- 刷新指令
- falush PRIVILEGES;
- -- 删除 点点这个用户
- DROP USER 'diandian'@'localhost'
细节说明:
- -- 说明 用户管理的细节
- -- 在创建用户的时候,如果不指定Host,则为%,% 表示所有ip都可以连接权限,create user XXX;
- CREATE USER jack;
- SELECT `host`,`user` FROM mysql.user;
- -- 你也可以这样指定 create user 'XXX' @'192.168.1.%' 表示xxx 用户在192.168.1* 的ip可以登录MySQL
- CREATE USER 'tiantian'@'192.168.1.%'
- -- 在删除用户的时候,如果host 不是%,需要明确指定’用户‘@'host值'
- DROP USER jack -- 默认就是 drop user 'jack'@'%'
- DROP USER tiantian -- 失败
- DROP USER 'tiantian'@'192.168.1.%'