mysql的数据操作和内置功能总结

Posted fanhk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql的数据操作和内置功能总结相关的知识,希望对你有一定的参考价值。

一.数据的增删改查

1.插入数据

a.插入完整数据(顺序插入)

INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n);
INSERT INTO 表名 VALUES (值1,值2,值3…值n);

b.指定字段插入数据

INSERT INTO 表名(字段1,字段2,字段3…) VALUES (值1,值2,值3…);

c.插入多条记录

INSERT INTO 表名 VALUES(值1,值2,值3…值n),(值1,值2,值3…值n),(值1,值2,值3…值n);

d.插入查询结果

INSERT INTO 表名(字段1,字段2,字段3…字段n) SELECT (字段1,字段2,字段3…字段n) FROM 表2 WHERE …;

2.更新数据

UPDATE 表名 SET 字段1=值1,字段2=值2 ... WHERE CONDITION;

3.删除数据

DELETE FROM 表名 WHERE CONITION;

4.查询数据

a.单表查询语句

SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数

执行优先级from->where->group by->having->select->distinct->order by->limit

1.找到表:from 2.拿着where指定的约束条件去文件/表中取出一条条记录 3.将取出的一条条记录进行分组group by,如果没有group by则整体作为一组 4.将分组的结果进行having过滤 5.执行select 6.去重 7.将结果按条件排序:order by 8.限制结果的显示条数

#简单查询
SELECT id,name,sex,age,hire_date,post,post_comment,salary,office,depart_id FROM employee;
SELECT * FROM employee;
SELECT name,salary FROM employee;

#避免重复DISTINCT
SELECT DISTINCT post FROM employee;    

#通过四则运算查询
SELECT name, salary*12 FROM employee;
SELECT name, salary*12 AS Annual_salary FROM employee;
SELECT name, salary*12 Annual_salary FROM employee;

#定义显示格式
CONCAT() 函数用于连接字符串
SELECT CONCAT(姓名:,name,年薪:, salary*12)  AS Annual_salary FROM employee;

CONCAT_WS() 第一个参数为分隔符
SELECT CONCAT_WS(:,name,salary*12)  AS Annual_salary FROM employee;

where条件

where字句中可以使用:

比较运算符:><>= <= <> !=

between 80 and 100 值在10到20之间

in(80,90,100) 值是10或20或30

like ‘egon%‘ pattern可以是%或_, %表示任意多字符 _表示一个字符

逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not

SELECT name FROM employee WHERE post=sale;
SELECT name,salary FROM employee WHERE post=teacher AND salary>10000;
SELECT name,salary FROM employee WHERE salary BETWEEN 10000 AND 20000;
SELECT name,post_comment FROM employee WHERE post_comment IS NOT NULL;
SELECT name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ;
SELECT * FROM employee WHERE name LIKE eg%;

分组查询group by

#1、首先明确一点:分组发生在where之后,即分组是基于where之后得到的记录而进行的

#2、分组指的是:将所有记录按照某个相同字段进行归类,比如针对员工信息表的职位分组,或者按照性别进行分组等

#3、可以按照任意字段分组,但是分组完毕后,比如group by post,只能查看post字段,如果想查看组内信息,需要借助于聚合函数 

SELECT post FROM employee GROUP BY post;
SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post; #按照岗位分组,并查看组内成员名
select post,count(id) as count from employee group by post; #按照岗位分组,并查看每个组有多少人

HAVING 过滤

#1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。

#2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数。

select post,group_concat(name),count(id) from employee group by post having count(id) < 2;
select post,avg(salary) from employee group by post having avg(salary) > 10000 and avg(salary) <20000;

查询排序 ORDER BY

按单列排序
SELECT * FROM employee ORDER BY salary;
SELECT * FROM employee ORDER BY salary ASC;
SELECT * FROM employee ORDER BY salary DESC;

按多列排序:先按照age排序,如果年纪相同,则按照薪资排序
SELECT * from employee ORDER BY age,salary DESC;

限制查询记录数LIMIT

SELECT * FROM employee ORDER BY salary DESC LIMIT 3; #默认初始位置为0,显示前3条
SELECT * FROM employee ORDER BY salary DESC LIMIT 0,5; #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
SELECT * FROM employee ORDER BY salary DESC LIMIT 5,5; #从第5开始,即先查询出第6条,然后包含这一条在内往后查5条

b. 多表查询

 多表连接查询

SELECT 字段列表 FROM 表1 INNER|LEFT|RIGHT JOIN 表2 ON 表1.字段 = 表2.字段;
交叉连接:不用任何条件,笛卡尔积
mysql> select * from employee,department;
+----+------------+--------+------+--------+------+--------------+
| id | name       | sex    | age  | dep_id | id   | name         |
+----+------------+--------+------+--------+------+--------------+
|  1 | egon       | male   |   18 |    200 |  200 | 技术         |
|  1 | egon       | male   |   18 |    200 |  201 | 人力资源     |
|  1 | egon       | male   |   18 |    200 |  202 | 销售         |
|  1 | egon       | male   |   18 |    200 |  203 | 运营         |
|  2 | alex       | female |   48 |    201 |  200 | 技术         |
|  2 | alex       | female |   48 |    201 |  201 | 人力资源     |
|  2 | alex       | female |   48 |    201 |  202 | 销售         |
|  2 | alex       | female |   48 |    201 |  203 | 运营         |
|  3 | wupeiqi    | male   |   38 |    201 |  200 | 技术         |
|  3 | wupeiqi    | male   |   38 |    201 |  201 | 人力资源     |
|  3 | wupeiqi    | male   |   38 |    201 |  202 | 销售         |
|  3 | wupeiqi    | male   |   38 |    201 |  203 | 运营         |
|  4 | yuanhao    | female |   28 |    202 |  200 | 技术         |
|  4 | yuanhao    | female |   28 |    202 |  201 | 人力资源     |
|  4 | yuanhao    | female |   28 |    202 |  202 | 销售         |
|  4 | yuanhao    | female |   28 |    202 |  203 | 运营         |
|  5 | liwenzhou  | male   |   18 |    200 |  200 | 技术         |
|  5 | liwenzhou  | male   |   18 |    200 |  201 | 人力资源     |
|  5 | liwenzhou  | male   |   18 |    200 |  202 | 销售         |
|  5 | liwenzhou  | male   |   18 |    200 |  203 | 运营         |
|  6 | jingliyang | female |   18 |    204 |  200 | 技术         |
|  6 | jingliyang | female |   18 |    204 |  201 | 人力资源     |
|  6 | jingliyang | female |   18 |    204 |  202 | 销售         |
|  6 | jingliyang | female |   18 |    204 |  203 | 运营         |
+----+------------+--------+------+--------+------+--------------+
内连接只连接匹配行
mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id; 
+----+-----------+------+--------+--------------+
| id | name      | age  | sex    | name         |
+----+-----------+------+--------+--------------+
|  1 | egon      |   18 | male   | 技术         |
|  2 | alex      |   48 | female | 人力资源     |
|  3 | wupeiqi   |   38 | male   | 人力资源     |
|  4 | yuanhao   |   28 | female | 销售         |
|  5 | liwenzhou |   18 | male   | 技术         |
+----+-----------+------+--------+--------------+
外链接之左连接:优先显示左表全部记录 
mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
+----+------------+--------------+
| id | name       | depart_name  |
+----+------------+--------------+
|  1 | egon       | 技术         |
|  5 | liwenzhou  | 技术         |
|  2 | alex       | 人力资源     |
|  3 | wupeiqi    | 人力资源     |
|  4 | yuanhao    | 销售         |
|  6 | jingliyang | NULL         |
+----+------------+--------------+
外链接之右连接:优先显示右表全部记录
mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
+------+-----------+--------------+
| id   | name      | depart_name  |
+------+-----------+--------------+
|    1 | egon      | 技术         |
|    2 | alex      | 人力资源     |
|    3 | wupeiqi   | 人力资源     |
|    4 | yuanhao   | 销售         |
|    5 | liwenzhou | 技术         |
| NULL | NULL      | 运营         |
+------+-----------+--------------+
全外连接:显示左右两个表全部记录

 

select * from employee left join department on employee.dep_id = department.id
union
select * from employee right join department on employee.dep_id = department.id;
#查看结果
+------+------------+--------+------+--------+------+--------------+
| id   | name       | sex    | age  | dep_id | id   | name         |
+------+------------+--------+------+--------+------+--------------+
|    1 | egon       | male   |   18 |    200 |  200 | 技术         |
|    5 | liwenzhou  | male   |   18 |    200 |  200 | 技术         |
|    2 | alex       | female |   48 |    201 |  201 | 人力资源     |
|    3 | wupeiqi    | male   |   38 |    201 |  201 | 人力资源     |
|    4 | yuanhao    | female |   28 |    202 |  202 | 销售         |
|    6 | jingliyang | female |   18 |    204 | NULL | NULL         |
| NULL | NULL       | NULL   | NULL |   NULL |  203 | 运营         |
+------+------------+--------+------+--------+------+--------------+

#注意 union与union all的区别:union会去掉相同的纪录

符合条件连接查询

#示例1:以内连接的方式查询employee和department表,并且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门
select employee.name,department.name from employee inner join department on employee.dep_id = department.id where age > 25;

#示例2:以内连接的方式查询employee和department表,并且以age字段的升序方式显示
select employee.id,employee.name,employee.age,department.name from employee,department where employee.dep_id = department.id and age > 25 order by age asc;

子查询

#1:子查询是将一个查询语句嵌套在另一个查询语句中。

#2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。

#3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字

#4:还可以包含比较运算符:= 、 !=、> 、<等

#查询平均年龄在25岁以上的部门名
select id,name from department where id in (select dep_id from employee group by dep_id having avg(age) > 25);
#查询大于所有人平均年龄的员工名与年龄
mysql> select name,age from emp where age > (select avg(age) from emp);
#department表中存在dept_id=200,Ture
select * from employee where exists (select id from department where id=200);

二.内置功能

 1.视图

 视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,可以将该结果集当做表来使用。

 创建视图

CREATE VIEW 视图名称 AS  SQL语句
create view teacher_view as select tid from teacher where tname=李平老师;

使用视图

select cname from course where teacher_id = (select tid from teacher_view);

修改视图

ALTER VIEW 视图名称 AS SQL语句
alter view teacher_view as select * from course where cid>3;

删除视图

DROP VIEW 视图名称
DROP VIEW teacher_view

2.触发器

 使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为

# 插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END
# 插入后
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END
# 删除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END
# 删除后
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END
# 更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END
# 更新后
CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END
#创建触发器
delimiter //
CREATE TRIGGER tri_after_insert_cmd AFTER INSERT ON cmd FOR EACH ROW
BEGIN
    IF NEW.success = no THEN #等值判断只有一个等号
        INSERT INTO errlog(err_cmd, err_time) VALUES (NEW.cmd,NEW.sub_time); #必须加分号
    END IF ; #必须加分号
END//
delimiter ;

删除触发器

drop trigger tri_after_insert_cmd;

3. 事务

 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。

#原子操作
start transaction;
update user set balance=900 where name=wsb; #买支付100元
update user set balance=1010 where name=egon; #中介拿走10元
update user set balance=1090 where name=ysb; #卖家拿到90元
commit;

#出现异常,回滚到初始状态
start transaction;
update user set balance=900 where name=wsb; #买支付100元
update user set balance=1010 where name=egon; #中介拿走10元
uppdate user set balance=1090 where name=ysb; #卖家拿到90元,出现异常没有拿到
rollback;
commit;

4.存储过程

存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql

使用存储过程的优点:

#1. 用于替代程序写的SQL语句,实现程序与sql解耦

#2. 基于网络传输,传别名的数据量小,而直接传sql数据量大

使用存储过程的缺点:

#1. 程序员扩展功能不方便

 创建存储过程

delimiter //
create procedure p1()
BEGIN
    select * from blog;
    INSERT into blog(name,sub_time) values("xxx",now());
END //
delimiter ;

#在mysql中调用
call p1() 

#在python中基于pymysql调用
cursor.callproc(p1) 
print(cursor.fetchall())

对于存储过程,可以接收参数,其参数有三类:

#in 仅用于传入参数用

#out 仅用于返回值用

#inout 既可以传入又可以当作返回值

delimiter //
create procedure p3(
    in n1 int,
    out res int
)
BEGIN
    select * from blog where id > n1;
    set res = 1;
END //
delimiter ;

#在mysql中调用
set @res=0; #0代表假(执行失败),1代表真(执行成功)
call p3(3,@res);
select @res;

#在python中基于pymysql调用
cursor.callproc(p3,(3,0)) #0相当于set @res=0
print(cursor.fetchall()) #查询select的查询结果

cursor.execute(select @_p3_0,@_p3_1;) #@p3_0代表第一个参数@p3_1代表第二个参数,即返回值
print(cursor.fetchall())

out:返回值

5.函数

一、数学函数
    ROUND(x,y)
        返回参数x的四舍五入的有y位小数的值

    RAND()
        返回0到1内的随机值,可以通过提供一个参数(种子)使RAND()随机数生成器生成一个指定的值。

二、聚合函数(常用于GROUP BY从句的SELECT查询中)
    AVG(col)返回指定列的平均值
    COUNT(col)返回指定列中非NULL值的个数
    MIN(col)返回指定列的最小值
    MAX(col)返回指定列的最大值
    SUM(col)返回指定列的所有值之和
    GROUP_CONCAT(col) 返回由属于一组的列值连接组合而成的结果    

三、字符串函数

    CHAR_LENGTH(str)
        返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算作一个单字符。
    CONCAT(str1,str2,...)
        字符串拼接
        如有任何一个参数为NULL ,则返回值为 NULL。
    CONCAT_WS(separator,str1,str2,...)
        字符串拼接(自定义连接符)
        CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。

    CONV(N,from_base,to_base)
        进制转换
        例如:
            SELECT CONV(a,16,2); 表示将 a 由16进制转换为2进制字符串表示

    FORMAT(X,D)
        将数字X 的格式写为#,###,###.##,以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若  D 为 0, 则返回结果不带有小数点,或不含小数部分。
        例如:
            SELECT FORMAT(12332.1,4); 结果为: 12,332.1000
    INSERT(str,pos,len,newstr)
        在str的指定位置插入字符串
            pos:要替换位置其实位置
            len:替换的长度
            newstr:新字符串
        特别的:
            如果pos超过原字符串长度,则返回原字符串
            如果len超过原字符串长度,则由新字符串完全替换
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一个出现位置。

    LEFT(str,len)
        返回字符串str 从开始的len位置的子序列字符。

    LOWER(str)
        变小写

    UPPER(str)
        变大写

    REVERSE(str)
        返回字符串 str ,顺序和字符顺序相反。

    SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
        不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 
     使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。 mysql
> SELECT SUBSTRING(Quadratically,5); -> ratically mysql> SELECT SUBSTRING(foobarbar FROM 4); -> barbar mysql> SELECT SUBSTRING(Quadratically,5,6); -> ratica mysql> SELECT SUBSTRING(Sakila, -3); -> ila mysql> SELECT SUBSTRING(Sakila, -5, 3); -> aki mysql> SELECT SUBSTRING(Sakila FROM -4 FOR 2); -> ki 四、日期和时间函数 CURDATE()或CURRENT_DATE() 返回当前的日期 CURTIME()或CURRENT_TIME() 返回当前的时间 DAYOFWEEK(date) 返回date所代表的一星期中的第几天(1~7) DAYOFMONTH(date) 返回date是一个月的第几天(1~31) DAYOFYEAR(date) 返回date是一年的第几天(1~366) DAYNAME(date) 返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE); FROM_UNIXTIME(ts,fmt) 根据指定的fmt格式,格式化UNIX时间戳ts HOUR(time) 返回time的小时值(0~23) MINUTE(time) 返回time的分钟值(0~59) MONTH(date) 返回date的月份值(1~12) MONTHNAME(date) 返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE); NOW() 返回当前的日期和时间 QUARTER(date) 返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE); WEEK(date) 返回日期date为一年中第几周(0~53) YEAR(date) 返回日期date的年份(1000~9999) 重点: DATE_FORMAT(date,format) 根据format字符串格式化date值 mysql> SELECT DATE_FORMAT(2009-10-04 22:23:00, %W %M %Y); -> Sunday October 2009 mysql> SELECT DATE_FORMAT(2007-10-04 22:23:00, %H:%i:%s); -> 22:23:00 mysql> SELECT DATE_FORMAT(1900-10-04 22:23:00, -> %D %y %a %d %m %b %j); -> 4th 00 Thu 04 10 Oct 277 mysql> SELECT DATE_FORMAT(1997-10-04 22:23:00, -> %H %k %I %r %T %S %w); -> 22 22 10 10:23:00 PM 22:23:00 00 6 mysql> SELECT DATE_FORMAT(1999-01-01, %X %V); -> 1998 52 mysql> SELECT DATE_FORMAT(2006-06-00, %d); -> 00 五、加密函数 MD5() 计算字符串str的MD5校验和 PASSWORD(str) 返回字符串str的加密版本,这个加密过程是不可逆转的,和UNIX密码加密过程使用不同的算法。 六、控制流函数 CASE WHEN[test1] THEN [result1]...ELSE [default] END 如果testN是真,则返回resultN,否则返回default CASE [test] WHEN[val1] THEN [result]...ELSE [default]END 如果test和valN相等,则返回resultN,否则返回default IF(test,t,f) 如果test是真,返回t;否则返回f IFNULL(arg1,arg2) 如果arg1不是空,返回arg1,否则返回arg2 NULLIF(arg1,arg2) 如果arg1=arg2返回NULL;否则返回arg1

6.流程控制

条件例子

delimiter //
CREATE PROCEDURE proc_if ()
BEGIN

    declare i int default 0;
    if i = 1 THEN
        SELECT 1;
    ELSEIF i = 2 THEN
        SELECT 2;
    ELSE
        SELECT 7;
    END IF;

END //
delimiter ;

if条件语句

循环例子

delimiter //
CREATE PROCEDURE proc_while ()
BEGIN

    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;
        SET num = num + 1 ;
    END WHILE ;

END //
delimiter ;

while循环

7.索引

功能

 #1. 索引的功能就是加速查找

 #2. mysql中的primary key,unique,联合唯一也都是索引,这些索引除了加速查找以外,还有约束的功能

常见索引

 普通索引INDEX:加速查找

 唯一索引:

 -主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复)

 -唯一索引UNIQUE:加速查找+约束(不能重复)

 联合索引:

 -PRIMARY KEY(id,name):联合主键索引

 -UNIQUE(id,name):联合唯一索引

 -INDEX(id,name):联合普通索引

 索引的两大类型hash与btree

#我们可以在创建上述索引的时候,为其指定索引类型,分两类

hash类型的索引:查询单条快,范围查询慢

btree类型的索引:b+树,层数越多,数据量指数级增长(我们就用它,因为innodb默认支持它)

#不同的存储引擎支持的索引类型也不一样

InnoDB 支持事务,支持行级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;

MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;

Memory 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;

NDB 支持事务,支持行级别锁定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;

Archive 不支持事务,支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引;

创建删除索引的方法 

#方法一:创建表时
      CREATE TABLE 表名 (
                字段名1  数据类型 [完整性约束条件…],
                字段名2  数据类型 [完整性约束条件…],
                [UNIQUE | FULLTEXT | SPATIAL ]   INDEX | KEY
                [索引名]  (字段名[(长度)]  [ASC |DESC]) 
                );


#方法二:CREATE在已存在的表上创建索引
        CREATE  [UNIQUE | FULLTEXT | SPATIAL ]  INDEX  索引名 
                     ON 表名 (字段名[(长度)]  [ASC |DESC]) ;


#方法三:ALTER TABLE在已存在的表上创建索引
        ALTER TABLE 表名 ADD  [UNIQUE | FULLTEXT | SPATIAL ] INDEX
                             索引名 (字段名[(长度)]  [ASC |DESC]) ;

#删除索引:DROP INDEX 索引名 ON 表名字;

 


以上是关于mysql的数据操作和内置功能总结的主要内容,如果未能解决你的问题,请参考以下文章

数据库:mysql内置功能-事务

mysql内置功能

数据库:mysql内置功能-触发器

MySQL触发器

mysql内置功能—视图

数据库:mysql内置功能-视图