MySQL学习笔记(三) 黄金

运算符

算术运算符

  • 加:+
  • 减:-
  • 乘:*
  • 除:/  或  div
    •     div只保留整数部分
  • 模:%  或  mod
#查询员工的姓名和原来的薪资和涨薪1000元后的薪资
SELECT ename,salary,salary + 1000 FROM t_employee;

#查询9/4的结果
SELECT 9/4

#查询9/4的结果
SELECT 9 DIV 4

#查询员工的姓名,和天天的薪资,假设每月的工做日是22天
SELECT ename AS "姓名", salary / 22 AS "日薪" FROM t_employee

#查询9%4的结果
SELECT 9%4, 9 MOD 4;

比较运算符

  • 大于:>
  • 小于:<
  • 大于等于:>=
  • 小于等于:<=
  • 等于:=    
    •    赋值和比较都是用=
  • 不等于:!=  或  <>
  • 安全等于:<=>
#查询薪资大于20000的员工
SELECT * FROM t_employee WHERE salary > 20000;

#查询薪资等于9000
SELECT * FROM t_employee WHERE salary = 9000;

#查询部门编号不是1的员工
SELECT * FROM t_employee WHERE did != 1;
SELECT * FROM t_employee WHERE did <> 1;

#查询奖金比例是NULL的员工

SELECT * FROM t_employee WHERE commission_pct <=> NULL;
SELECT * FROM t_employee WHERE commission_pct IS NULL;

逻辑运算符

  • 与:&& 或 and
  • 或:|| 或 or
  • 非:!  或 not
#查询薪资高于10000 而且低于15000的女员工
SELECT * FROM t_employee
WHERE salary > 10000 && salary <15000 AND gender = '女'

#查询薪资高于20000  或者  籍贯是 浙江
SELECT * FROM t_employee
WHERE salary > 20000 || native_place = '浙江';

#查询非浙江籍的男生
SELECT * FROM t_employee
WHERE NOT native_place = '浙江' AND gender = '男';

#查询奖金比例非空的员工
SELECT * FROM t_employee
WHERE commission_pct IS NOT NULL;

集合运算符

  • in (值列表)
  • not in(值列表)
#查询籍贯是 “浙江”、“北京”、“上海”、“黑龙江”的员工
SELECT * FROM t_employee
WHERE native_place IN ('浙江','上海','北京','黑龙江');

#查询籍贯不是 “浙江”、“北京”、“上海”、“黑龙江”的员工
SELECT * FROM t_employee
WHERE native_place NOT IN ('浙江','上海','北京','黑龙江');

区间范围

  • between xx and yy:[xx,yy]
  • not between xx and yy:  小于xx 或 大于yy
#查询薪资大于等于10000 而且小于等于15000的员工
SELECT * FROM t_employee
WHERE salary BETWEEN 10000 AND 15000;

关联查询

  • 内链接
  • 外链接
    • 左外链接:left join
    • 右外链接:right join
    • 全外链接:full join  mysql不支持

关联查询的结果一共有七种:
关联查询必须有两张或两张以上,如下用两张来示例:mysql

(1)A ∩ B用内链接sql

                               


(2)A用左链接数据库


(3)A - (A ∩ B)用左链接
                                  安全

(4)B    用右链接多线程

(5)B - A ∩ B用右链接
                        
(6)A ∪ B本类应该用全外链接,如今用union并发


(7)A ∪ B - A ∩ B本类应该用全外链接,如今用union
                                        函数


 

内链接

--形式一
select 字段列表
from A表 inner join B表
on 关联条件
【where 其余筛选条件】

--形式二
select 字段列表
from A表 , B表
where 关联条件 【and 其余筛选条件】
  • 若是不写关联条件,会出现一种现象:笛卡尔积(将两(或多)个表的全部行进行组合,链接后的行数为两(或多)个表的乘积数.
  •    关联条件的个数 = n - 1,n是几张表关联
  •    on只能和join一块儿用
#查询全部的员工的姓名和他所在部门的编号和部门的名称,不包括那些没有安排部门的员工
--形式一
select ename,t_employee.did,dname
from t_employee inner join t_department
on t_employee.did =t_department.did;

--形式二
SELECT ename,t_employee.did,dname 
FROM t_employee , t_department
WHERE t_employee.did = t_department.did ;


#查询全部的女员工的姓名和他所在部门的编号和部门的名称,不包括那些没有安排部门的员工
--1
SELECT ename,t_employee.did,dname 
FROM t_employee INNER JOIN t_department
ON t_employee.did = t_department.did
WHERE gender = '女';
--2
SELECT ename,t_employee.did,dname 
FROM t_employee , t_department
WHERE t_employee.did = t_department.did AND gender = '女';



#查询员工编号,员工的姓名,部门编号,部门名称,职位编号,职位名称
SELECT t_employee.eid, t_employee.`ename`, t_department.did,t_department.`dname`, t_job.`job_id`,t_job.`job_name`
FROM t_employee INNER JOIN t_department INNER JOIN t_job
ON t_employee.did = t_department.did AND t_employee.`job_id` = t_job.`job_id`

SELECT t_employee.eid, t_employee.`ename`, t_department.did,t_department.`dname`, t_job.`job_id`,t_job.`job_name`
FROM t_employee , t_department , t_job
WHERE t_employee.did = t_department.did AND t_employee.`job_id` = t_job.`job_id`

左链接和右链接

左链接和右链接的区别:
(1)left换成right
(2)以左边的表为主仍是以右边的表为主spa

--左链接
select 字段列表
from A表 left join B表
on 关联条件
where 从表的关联字段 is null

--右链接
select 字段列表
from A表 right join B表
on 关联条件
where 从表的关联字段 is null
#查询全部员工和他的部门编号,部门名称,包括那些没有部门的员工
SELECT * 
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did

#查询全部没有部门的员工

SELECT * 
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

全链接

mysql没有全链接,使用union实现全链接的效果线程

select 字段列表
from A表 left join B表
on 关联条件
union 
select 字段列表
from A表 right join B表
on 关联条件
#查询全部员工和部门信息,包括那些没有部门的员工和没有员工的部门
SELECT *
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
UNION
SELECT *
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did


#查询那些没有部门的员工和没有员工的部门
SELECT *
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL
UNION 
SELECT *
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

select语句的子句

以前:
select * from 表名称 【where 条件】;
select 字段列表 from 表名称 【where 条件】;3d

如今select 
select语句的5个子句:

  • (1)where
    •          where 条件   用于从表中筛选出符合条件的记录(行)
  • (2)group by
  • (3)having
  • (4)order by
  • (5)limit

这5个子句能够同时出现,也能够只出现其中的一部分,其中若是有having前面必须有group by,可是有group by不必定有having
若是5个子句有多个同时出现的,那么必须按照(1)-(5)的顺序

where

#查询全部的女员工
SELECT * FROM t_employee WHERE gender = '女';

#查询全部女员工的姓名和薪资
SELECT ename,salary FROM t_employee WHERE gender = '女';

group by

#查询每一个部门的平均工资
SELECT did,AVG(salary) FROM t_employee GROUP BY did;

#查询每一个部门的平均工资,排除没有部门的员工
SELECT did,AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did ;

#查询每一个部门的女员工的最高工资
SELECT did,MAX(salary) FROM t_employee WHERE gender = '女' GROUP BY did;
SELECT did,MAX(salary) FROM t_employee WHERE gender = '女' AND did IS NOT NULL GROUP BY did;

#查询男、女员工的平均工资
SELECT gender,AVG(salary) FROM t_employee GROUP BY gender;

#查询每一个部门的男、女员工的平均工资分别是多少
#先按部门再按男女
SELECT did, gender, AVG(salary) FROM t_employee GROUP BY did,gender;
SELECT did, gender, AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did,gender;


#查询每一个部门的工资总数
SELECT did,SUM(salary) FROM t_employee GROUP BY did;

#查询每一个部门的男、女员工的人数
SELECT did, gender, COUNT(*) FROM t_employee WHERE did IS NOT NULL GROUP BY did,gender;

having

having只用于group by分组统计语句

where和having的区别:

  • (1)where后面是不容许使用分组函数,having后面能够加分组函数
  • where是用于“原”表中的记录的筛选,而having是用于“统计结果”的筛选
#查询每一个部门的平均工资,只显示平均工资在12000以上的
SELECT did,AVG(salary) FROM t_employee  GROUP BY did HAVING AVG(salary) > 12000

#查询每一个部门的最高工资,要求显示最高工资低于12000
SELECT did,MAX(salary) FROM t_employee GROUP BY did HAVING MAX(salary) < 12000
SELECT did,MAX(salary) AS "m" FROM t_employee GROUP BY did HAVING m < 12000

order by

按一个或多个字段对查询结果进行排序,asc是升序,desc为降序,默认是升序

#查询员工的姓名和薪资,按照薪资的从高到低排序
SELECT ename,salary FROM t_employee ORDER BY salary DESC;


#查询员工的编号,姓名和薪资,按照薪资的从高到低排序,若是薪资相同,再按照编号升序排列
SELECT eid,ename,salary FROM t_employee ORDER BY salary DESC,eid ASC;


#查询每一个部门的平均工资,按照平均工资的升序排序
SELECT did,AVG(salary) FROM t_employee GROUP BY did ORDER BY AVG(salary) ASC;


#查询每一个部门的女员工的平均工资,按照平均工资的升序排序,而且只显示平均工资高于12000的
SELECT did,AVG(salary) 
FROM t_employee 
WHERE gender = '女' 
GROUP BY did 
HAVING AVG(salary) > 12000
ORDER BY AVG(salary) ASC;

limit 分页

limit m,n
m = (page - 1)*每页的记录数
n = 每页的记录数

#查询员工信息,每页显示10条,显示第一页
SELECT * FROM t_employee LIMIT 0,10

#查询员工信息,每页显示10条,显示第二页
SELECT * FROM t_employee LIMIT 10,10

#查询每一个部门的女员工的平均工资,按照平均工资的升序排序,而且只显示平均工资高于12000的,
#每页显示1条,显示第二页
SELECT did,AVG(salary) 
FROM t_employee 
WHERE gender = '女' 
GROUP BY did 
HAVING AVG(salary) > 12000
ORDER BY AVG(salary) ASC
LIMIT 1,1;

子查询

某些状况下,当进行一个查询时,须要的条件或数据要用另一个 select 语句的结果,这个时候,就要用到子查询。

  • 为了给主查询(外部查询)提供数据而首先执行的查询(内部查询)被叫作子查询。
  • 通常根据子查询的嵌入位置分为,where型子查询,from型子查询,exists型子查询。

where型子查询

  1. 子查询要包含在括号内。
  2. 建议将子查询放在比较条件的右侧。
  3. 单行操做符对应单行子查询,多行操做符对应多行子查询。

 条件的运算符分为两类:
    =,>,>=,<,<=,!=  后面接子查询的结果必须是“单值”
    in, = any, >all,>= ,<all.....  后面接子查询的结果能够是“多值”

#查询全公司最高工资的员工的信息
#(1)查询最高工资
SELECT MAX(salary) FROM t_employee;

#(2)查询最高工资的员工的信息
SELECT * FROM t_employee WHERE salary = 130990

#(3)合起来
SELECT * FROM t_employee WHERE salary = (SELECT MAX(salary) FROM t_employee)

--------------------------------------------------------------------------
#查询和孙红雷,刘烨,范冰冰三我的中任意一个工资同样的员工
SELECT * FROM t_employee WHERE salary IN (SELECT salary FROM t_employee WHERE ename IN ('孙红雷','刘烨','范冰冰'))

SELECT * FROM t_employee WHERE salary = ANY (SELECT salary FROM t_employee WHERE ename IN ('孙红雷','刘烨','范冰冰'))


-------------------------------------------------------------------------

#查询比李冰冰工资高的女员工
SELECT * FROM t_employee WHERE gender = '女' AND salary > (SELECT salary FROM t_employee WHERE ename = '李冰冰');


#查询全公司最高工资的员工的信息
SELECT * FROM t_employee WHERE salary >= ALL(SELECT salary FROM t_employee)

from型

查询每一个部门编号,部门名称,和平均工资,排除没有部门的员工,包括那些没有员工的部门

SELECT t_department.*, temp.pingjun
FROM t_department LEFT JOIN (SELECT did,AVG(salary) AS pingjun FROM t_employee  WHERE did IS NOT NULL GROUP BY did) AS temp
ON t_department.did = temp.did

exists型

#查询部门信息,该部门必须有员工
SELECT * FROM t_department
WHERE EXISTS (SELECT * FROM t_employee WHERE t_employee.did = t_department.did)


#把SELECT * FROM t_department的每一行记录,根据t_employee.did = t_department.did,代入到(SELECT * FROM t_employee)中查,若是能够查到结果,说明该行要留下,不然就排除掉
 

#使用内链接查询,也能够实现
SELECT  DISTINCT t_department.* 
FROM t_department INNER JOIN t_employee
ON t_employee.did = t_department.did

单行函数(了解)

数学函数

ABS(x)

返回x的绝对值

CEIL(x)

返回大于x的最小整数值

FLOOR(x)

返回大于x的最大整数值

MOD(x,y)

返回x/y的模

RAND(x)

返回0~1的随机值

ROUND(x,y)

返回参数x的四舍五入的有y位的小数的值

TRUNCATE(x,y)

返回数字x截断为y位小数的结果

SQRT(x)

返回x的平方根

POW(x,y)

返回x的y次方

 

字符串函数

CONCAT(S1,S2,......,Sn)

链接S1,S2,......,Sn为一个字符串

CONCAT_WS(s, S1,S2,......,Sn)

同CONCAT(s1,s2,...)函数,可是每一个字符串之间要加上s

CHAR_LENGTH(s)

返回字符串s的字符数

LENGTH(s)

返回字符串s的字节数,和字符集有关

INSERT(str, index , len, instr)

将字符串str从第index位置开始,len个字符长的子串替换为字符串instr

UPPER(s) 或 UCASE(s)

将字符串s的全部字母转成大写字母

LOWER(s)  或LCASE(s)

将字符串s的全部字母转成小写字母

LEFT(s,n)

返回字符串s最左边的n个字符

RIGHT(s,n)

返回字符串s最右边的n个字符

LPAD(str, len, pad)

用字符串pad对str最左边进行填充,直到str的长度为len个字符

RPAD(str ,len, pad)

用字符串pad对str最右边进行填充,直到str的长度为len个字符

LTRIM(s)

去掉字符串s左侧的空格

RTRIM(s)

去掉字符串s右侧的空格

TRIM(s)

去掉字符串s开始与结尾的空格

TRIM(【BOTH 】s1 FROM s)

去掉字符串s开始与结尾的s1

TRIM(【LEADING】s1 FROM s)

去掉字符串s开始处的s1

TRIM(【TRAILING】s1 FROM s)

去掉字符串s结尾处的s1

REPEAT(str, n)

返回str重复n次的结果

REPLACE(str, a, b)

用字符串b替换字符串str中全部出现的字符串a

STRCMP(s1,s2)

比较字符串s1,s2

SUBSTRING(s,index,len)

返回从字符串s的index位置其len个字符

日期时间函数

CURDATE() 或 CURRENT_DATE()

返回当前日期

CURTIME() 或 CURRENT_TIME()

返回当前时间

NOW()

 

SYSDATE()

CURRENT_TIMESTAMP()

LOCALTIME()

LOCALTIMESTAMP()

返回当前系统日期时间

YEAR(date)

MONTH(date)

DAY(date)

HOUR(time)

MINUTE(time)

SECOND(time)

返回具体的时间值

WEEK(date)

WEEKOFYEAR(date)

返回一年中的第几周

DAYOFWEEK()

返回周几,注意:周日是1,周一是2,。。。周六是7

WEEKDAY(date)

返回周几,注意,周1是0,周2是1,。。。周日是6

DAYNAME(date)

返回星期:MONDAY,TUESDAY.....SUNDAY

MONTHNAME(date)

返回月份:January,。。。。。

DATEDIFF(date1,date2)

TIMEDIFF(time1, time2)

返回date1 - date2的日期间隔

返回time1 - time2的时间间隔

DATE_ADD(datetime, INTERVAL  expr  type)

返回与给定日期时间相差INTERVAL时间段的日期时间

DATE_FORMAT(datetime ,fmt)

按照字符串fmt格式化日期datetime值

STR_TO_DATE(str, fmt)

按照字符串fmt对str进行解析,解析为一个日期

 

流程函数

IF(value,t ,f)

若是value是真,返回t,不然返回f

IFNULL(value1, value2)

若是value1不为空,返回value1,不然返回value2

CASE

WHEN 条件1 THEN result1

WHEN 条件2 THEN result2

....

[ELSE resultn]

END

 

至关于Java的if...else if...

CASE  expr

WHEN 常量值1 THEN 值1

WHEN 常量值1 THEN 值1

....

[ELSE 值n]

END

至关于Java的switch

 

SELECT ename ,CASE

WHEN salary>=15000 THEN '高薪'

WHEN salary>=10000 THEN '潜力股'

WHEN salary>=8000 THEN '屌丝'

ELSE '草根'

END

FROM t_employee;

 

SELECT oid,`status`, CASE `status`

WHEN 1 THEN '未付款'

WHEN 2 THEN '已付款'

WHEN 3 THEN '已发货'

WHEN 4 THEN '确认收货'

ELSE '无效订单'

END

FROM t_order;

 

事务

表示一组操做(sql),要么同时成功,要么同时失败,那么这种操做就构成了一个事务。

例如:
    张三  给  李四  转帐  500元
    (1)把张三的余额减小500
    ...
    (2)把李四的余额增长500
    
    不容许出现:张三的钱减小了500,而李四的钱没有加。
须要在(1)以前开启事务,若是同时成功,那么就提交这个事务,不然就回滚(还原到(1))以前的状态。

 

事务的ACID特性

  • 原子性(Atomicity):原子意为最小的粒子,或者说不能再分的事物。数据库事务的不可再分的原则即为原子性。
  • 组成事务的全部SQL必须:要么所有执行,要么所有取消(就像上面的银行例子)。
  • 一致性(Consistency):指数据的规则,在事务前/后应保持一致
  • 隔离性(Isolation):简单点说,某个事务的操做对其余事务不可见的.
  • 持久性(Durability):当事务提交完成后,其影响应该保留下来,不能撤消

事务的用法

mysql默认状况下是自动提交事务模式,即执行一句,自动提交一句,一旦提交就不能回滚。
若是想要开始手动提交模式,那么能够经过如下语句完成: set autocommit = false;

  • 开启事务(start transaction)
  • 执行sql操做(普通sql操做)
  • 提交/回滚(commit/rollback)

建表的时候,选择 Innodb引擎才支持事务

#开启手动提交模式,做用范围是一次链接(从登陆到退出)
SET autocommit = FALSE;

DELETE FROM t_department WHERE did > 5;

INSERT INTO t_department VALUES(NULL,'yy','yyyy');

ROLLBACK;
#COMMIT;

mysql中只有Innodb引擎才支持事务。
事务只对DML语句有效,对DDL语句无效。

事务的隔离级别

对于同时运行的多个事务(多线程并发), 当这些事务访问数据库中相同的数据时, 若是没有采起必要的隔离机制, 就会致使各类并发问题: (问题的本质就是线程安全问题,共享数据的问题)

  • 脏读

     一个事务读取了另外一个事务还未提交的数据

  • 不可重复读

     一个事务读取了另外一个事务“修改”已提交的数据,致使一个事务期间对同一个数据的先后两次读取,结果不一致。

  • 幻读

     一个事务读取了另外一个事务新增长并已经提交的数据,致使一个事务期间记录数不同。
     一个事务读取了另外一个事务删除并已经提交的数据,致使一个事务期间记录数不同。

事务的隔离级别:
(1)READ-UNCOMMITTED:读取未提交的数据
(2)READ-COMMITTED:读取已提交的数据
(3)REPEATABLE-READ:可重复读取
(4)SERIALIZABLE:序列化

mysql的默认隔离级别是:(3)

若是当前链接的隔离级别是READ-UNCOMMITTED,你会读取到别人未提交的数据,这个现象称为脏读。
若是避免“脏读”,就是提升隔离级别,提升为READ-COMMITTED或它以上。

若是当前链接的隔离级别是READ-UNCOMMITTED和READ-COMMITTED,都会出现不可重复的的现象,
若是要避免“不可重复读”,仍是提升隔离级别,提升为REPEATABLE-READ或它以上。

(3)REPEATABLE-READ和(4)SERIALIZABLE都能避免脏读、不可重复读、幻读,那么有什么区别呢?
REPEATABLE-READ:行
SERIALIZABLE:表
相关文章
相关标签/搜索