使用mysql
- 展示数据库,使用数据库;展示数据表。
mysql> SHOW DATABASES;
+----------------------------+
| Database |
+----------------------------+
| blog |
| bookshop |
| boot_cache |
| bootvue |
| device |
| ems |
| febs_security |
| haiyu |
| information_schema |
| ldms |
| learn |
| mmt_cloud |
| mydb |
| mysql |
| nacos_config |
| performance_schema |
| practice_teaching_base_ems |
| security |
| spring_cloud |
| ssm |
| sys |
+----------------------------+
21 rows in set (0.00 sec)
mysql> USE learn;
Database changed
mysql> SHOW TABLES;
+-----------------+
| Tables_in_learn |
+-----------------+
| city |
| dept |
| emp |
| emp_bak |
| myview1 |
| pro |
| salgrade |
| t_act |
| t_user |
| user |
| user_tbl |
+-----------------+
11 rows in set (0.00 sec)
- 显示表列
1、SHOW COLUMNS FROM emp;
2、DESCRIBE emp;
mysql> DESCRIBE emp;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO | int | NO | PRI | NULL | |
| ENAME | varchar(10) | YES | | NULL | |
| JOB | varchar(9) | YES | | NULL | |
| MGR | int | YES | | NULL | |
| HIREDATE | date | YES | | NULL | |
| SAL | double(7,2) | YES | | NULL | |
| COMM | double(7,2) | YES | | NULL | |
| DEPTNO | int | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
检索数据
- 检索单列
- 检索多列(,)
- 检索所有列(*)
- 检索不同的行
mysql> SELECT deptno FROM emp;
+--------+
| deptno |
+--------+
| 20 |
| 30 |
| 30 |
| 20 |
| 30 |
| 30 |
| 10 |
| 20 |
| 10 |
| 30 |
| 20 |
| 30 |
| 20 |
| 10 |
+--------+
14 rows in set (0.00 sec)
# 解决办法是使用DISTINCT关键字,顾名思义,此关键字指示MySQL只返回不同的值。
mysql> SELECT DISTINCT deptno FROM emp;
+--------+
| deptno |
+--------+
| 20 |
| 30 |
| 10 |
+--------+
3 rows in set (0.00 sec)
- 限制结果
mysql> SELECT ename FROM emp LIMIT 5;
+--------+
| ename |
+--------+
| SMITH |
| ALLEN |
| WARD |
| JONES |
| MARTIN |
+--------+
5 rows in set (0.01 sec)
# LIMIT 5指示MySQL返回不多于5行。
mysql> SELECT ename FROM emp LIMIT 3, 4;
mysql> SELECT ename FROM emp LIMIT 4 OFFSET 3;
+--------+
| ename |
+--------+
| JONES |
| MARTIN |
| BLAKE |
| CLARK |
+--------+
4 rows in set (0.00 sec)
# LIMIT 3, 4(LIMIT 4 OFFSET 3)指示MySQL返回从行3开始的4行。
排序检索数据
- 排序数据(ORDER BY)
- 按多个排序(排序按顺序进行)
- 指定排序方向(DESC降序,默认ASC升序)
过滤数据
-
使用WHERE子句
-
WHERE子句操作符(<>、!=不等于,BETWEEN在指定的两个值之间)
mysql> SELECT * FROM emp WHERE sal BETWEEN 1000 AND 2000;
+-------+--------+----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+----------+------+------------+---------+---------+--------+
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+----------+------+------------+---------+---------+--------+
6 rows in set (0.00 sec)
- 空值检查(IS NULL)
mysql> SELECT * FROM emp WHERE mgr IS NULL;
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
+-------+-------+-----------+------+------------+---------+------+--------+
1 row in set (0.00 sec)
-
OR操作符
-
计算次序(OR操作符优先级高于AND操作符)
在WHERE子句中使用圆括号 任何时候使用具有AND和OR操作符的WHERE子句,都应该使用圆括号明确地分组操作符。不要过分依赖默认计算次序,即使它确实是你想要的东西也是如此。使用圆括号没有什么坏处,它能消除歧义。
-
IN操作符(指定条件范围)
-
NOT操作符(有且只有一个功能,否定它之后所跟的任何条件)
用通配符进行过滤
-
LIKE操作符
- 通配符(wildcard)
- %(表示任何字符出现任意次数,%不能匹配NULL。)
- _(总是匹配单个字符)
- 搜索模式(search pattern)
- 通配符(wildcard)
-
使用通配符的技巧
正如所见, MySQL的通配符很有用。但这种功能是有代价的:通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给出一些使用通配符要记住的技巧。
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该
使用其他操作符。- 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用
在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起
来是最慢的。- 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。
用正则表达式进行搜索
- 基本字符匹配
mysql> SELECT ename FROM emp WHERE ename REGEXP 'O';
+-------+
| ename |
+-------+
| JONES |
| SCOTT |
| FORD |
+-------+
3 rows in set (0.14 sec)
# 除关键字LIKE被REGEXP替代外,这条语句看上去非常像使用LIKE的语句。
# LIKE匹配整个列。如果被匹配的文本在列值中出现,LIKE将不会找到它,相应的行也不被返回(除非使用通配符)。而REGEXP在列值内进行匹配,如果被匹配的文本在列值中出现, REGEXP将会找到它,相应的行将被返回。这是一个非常重要的差别。
- 进行OR匹配(使用 |,可以给出两个以上的OR条件,如:'1000 | 2000 | 3000')
- 匹配几个字符之一(使用 [ ])
- 匹配范围([0-9],[a-z])
- 匹配特殊字符(
\.表示查找. \-表示查找-
) - 匹配字符类
- 匹配多个实例
- 定位符
创建计算字段
- 拼接
mysql> SELECT concat( ename, '(', sal, ')' ) AS 'emp(sal)' FROM emp ORDER BY sal;
+-----------------+
| emp(sal) |
+-----------------+
| SMITH(800.00) |
| JAMES(950.00) |
| ADAMS(1100.00) |
| WARD(1250.00) |
| MARTIN(1250.00) |
| MILLER(1300.00) |
| TURNER(1500.00) |
| ALLEN(1600.00) |
| CLARK(2695.00) |
| SCOTT(3000.00) |
| FORD(3000.00) |
| BLAKE(3135.00) |
| JONES(3272.50) |
| KING(5000.00) |
+-----------------+
14 rows in set (0.00 sec)
- 使用别名(AS)
- 执行算术计算(列名进行+-*/)
使用数据处理函数
- 文本处理函数
函数 | 说明 |
---|---|
Left() | 返回串左边的字符 |
Length() | 返回串的长度 |
Locate() | 找出串的一个子串 |
Lower() | 将串转换为小写 |
LTrim() | 去掉串左边的空格 |
Right() | 返回串右边的字符 |
RTrim() | 去掉串右边的空格 |
Soundex() | 返回串的SOUNDEX值 |
SubString() | 返回子串的字符 |
Upper() | 将串转换为大写 |
- 日期和时间处理函数
# 匹配日期
mysql> SELECT * FROM emp WHERE date( hiredate ) = '87-04-19';
+-------+-------+---------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+---------+------+------------+---------+------+--------+
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
+-------+-------+---------+------+------------+---------+------+--------+
1 row in set (0.00 sec)
# 匹配日期范围
mysql> SELECT * FROM emp WHERE year( hiredate ) = '1981' and month( hiredate ) = '02';
+-------+-------+----------+------+------------+---------+--------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+----------+------+------------+---------+--------+--------+
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
+-------+-------+----------+------+------------+---------+--------+--------+
2 rows in set (0.02 sec)
如果要的是日期,请使用Date() 如果你想要的仅是日期,则使用Date()是一个良好的习惯,即使你知道相应的列只包含日期也是如此。这样,如果由于某种原因表中以后有日期和时间值,你的SQL代码也不用改变。当然,也存在一个Time()函数,在你只想要时间时应该使用它。
Date()和Time()都是在MySQL 4.1.1中第一次引入的。
- 数值处理函数
函数 | 说明 |
---|---|
Abs() | 返回一个数的绝对值 |
Cos() | 返回一个角度的余弦 |
Exp() | 返回一个数的指数值 |
Mod() | 返回除操作的余数 |
Pi() | 返回圆周率 |
Rand() | 返回一个随机数 |
Sin() | 返回一个角度的正弦 |
Sqrt() | 返回一个数的平方根 |
Tan() | 返回一个角度的正切 |
汇总数据
- 聚集函数
- AVG()
- COUNT()
- MAX()
- MIN()
- SUM()
- 聚集不同值
mysql> select avg(distinct sal) as avg_sal from emp;
+-------------+
| avg_sal |
+-------------+
| 2133.541667 |
+-------------+
1 row in set (0.00 sec)
- 组合聚集函数
mysql> select count(*) as num_items, min(sal) as min_sal, max(sal) as max_sal, avg(sal) as avg_sal from emp;
+-----------+---------+---------+-------------+
| num_items | min_sal | max_sal | avg_sal |
+-----------+---------+---------+-------------+
| 14 | 800.00 | 5000.00 | 2132.321429 |
+-----------+---------+---------+-------------+
1 row in set (0.00 sec)
分组数据
-
数据分组( count(*) )
-
创建分组(GROUP BY)
mysql> select sum(sal),avg(sal),count(*) from emp group by deptno;
+----------+-------------+----------+
| sum(sal) | avg(sal) | count(*) |
+----------+-------------+----------+
| 11172.50 | 2234.500000 | 5 |
| 9685.00 | 1614.166667 | 6 |
| 8995.00 | 2998.333333 | 3 |
+----------+-------------+----------+
3 rows in set (0.00 sec)
- 过滤分组(HAVING)
- WHERE过滤行,HAVING过滤分组;
- WHERE在数据分组前过滤,HAVING在数据分组后过滤。
mysql> select count(*) from emp group by deptno having count(*)>3;
+----------+
| count(*) |
+----------+
| 5 |
| 6 |
+----------+
2 rows in set (0.01 sec)
- 分组和排序(GROUP BY 和 ORDER BY)
- SELECT字句顺序
子句 | 说明 | 是否必须使用 |
---|---|---|
SELECT | 要返回的列或表达式 | 是 |
FROM | 从中检索数据的表 | 仅在从表选择数据时使用 |
WHERE | 行级过滤 | 否 |
GROUP BY | 分组说明 | 仅在按组计算聚集时使用 |
HAVING | 组级过滤 | 否 |
ORDER BY | 输出排序顺序 | 否 |
LIMIT | 要检索的行数 | 否 |
使用子查询
- 子查询(结合IN操作符使用)
- 作为计算字段使用子查询
联结表
- 创建联结(WHERE指定联结条件)
- 笛卡尔积
由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
应该保证所有联结都有WHERE子句,否则MySQL将返回比想要的数据多得多的数据。同理,应该保证WHERE子句的正确性。不正确的过滤条件将导致MySQL返回不正确的数据。
消除笛卡尔积最简单最直接的方式:使用等值连接。
mysql> select dname,ename from dept,emp where dept.deptno=emp.deptno;
+------------+--------+
| dname | ename |
+------------+--------+
| RESEARCH | SMITH |
| SALES | ALLEN |
| SALES | WARD |
| RESEARCH | JONES |
| SALES | MARTIN |
| SALES | BLAKE |
| ACCOUNTING | CLARK |
| RESEARCH | SCOTT |
| ACCOUNTING | KING |
| SALES | TURNER |
| RESEARCH | ADAMS |
| SALES | JAMES |
| RESEARCH | FORD |
| ACCOUNTING | MILLER |
+------------+--------+
14 rows in set (0.00 sec)
- 内部联结(INNER JOIN)
ANSI SQL规范首选INNER JOIN语法。此外,尽管使用WHERE子句定义联结的确比较简单,但是使用明确的联结语法能够确保不会忘记联结条件,有时候这样做也能影响性能。
- 联结多个表
MySQL在运行时关联指定的每个表以处理联结。这种处理可能是非常耗费资源的,因此应该仔细,不要联结不必要的表。联结的表越多,性能下降越厉害。
创建高级联结
-
使用表别名
-
使用不同类型的联结
- 自联结
使用自联结而不用子查询:
自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句。虽然最终的结果是相同的,但有时候处理联结远比处理子查询快得多。
- 自然联结(自然联结排除多次出现,使每个列只返回一次。一般使用通配符:SELECT *)
- 外部联结
- 左连接(LEFT JOIN)
- 右链接(RIGHT JOIN)
-
使用带聚集函数的联结
-
使用联结和联结条件(应该总是提供联结条件,否则会得出笛卡尔积。)
组合查询
- 创建组合查询(UNION)
mysql> (select ename,sal,deptno from emp where deptno in(10,20)) union (select ename,sal,deptno from emp where sal>=3000);
+--------+---------+--------+
| ename | sal | deptno |
+--------+---------+--------+
| SMITH | 800.00 | 20 |
| JONES | 3272.50 | 20 |
| CLARK | 2695.00 | 10 |
| SCOTT | 3000.00 | 20 |
| KING | 5000.00 | 10 |
| ADAMS | 1100.00 | 20 |
| FORD | 3000.00 | 20 |
| MILLER | 1300.00 | 10 |
| BLAKE | 3135.00 | 30 |
+--------+---------+--------+
9 rows in set (0.00 sec)
- 包含或取消重复的行
在使用UNION时,重复的行被自动取消,若想放回所有行,使用UNION ALL而不是UNION。
- 对组合查询结果排序
SELECT语句的输出用ORDER BY子句排序。在用UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条ORDER BY子句。
全文本搜索(第18章)
插入数据
- 插入完整行
- 插入多个行
- 插入检索出的数据
mysql> insert into user(name) select name from user;
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from user;
+----+----------+
| id | name |
+----+----------+
| 11 | zhangsan |
| 13 | lisi |
| 14 | wangwu |
| 15 | zhangsan |
| 16 | lisi |
| 17 | wangwu |
+----+----------+
6 rows in set (0.00 sec)
# INSERT SELECT中SELECT语句可包含WHERE子句以过滤插入的数据。
更新和删除数据
-
更新数据(UPDATE ... SET ... WHERE ...)
-
删除数据(DELETE FROM ... WHERE ...)
DELETE删除数据而不是表本身,TRUNCATE更快(TRUNCATE实际是删除原来的表并重新创建一个表,而不是逐行删除表中的数据)。
创建表和操纵表
- 创建表(CREATE)
- 更新表(ALERT)
mysql> alter table user add age VARCHAR(20);
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select * from user;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 王五 | NULL |
+----+--------+------+
1 row in set (0.00 sec)
使用ALTER TABLE要极为小心,应该在进行改动前做一个完整的备份(模式和数据的备份)。数据
库表的更改不能撤销,如果增加了不需要的列,可能不能删除它们。类似地,如果删除了不应该删除的列,可能会丢失该列中的所有数据。
- 删除表(DROP)
- 重命名表(RENAME TABLE T1 to T2)
使用视图
- 视图
视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
为什么使用视图?
- 重用SQL语句
- 简化复杂的SQL操作。在编写查询后,可以方便地重用它而不必知道它的基本查询细节。
- 使用表的组成部分而不是整个表。
- 保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限。
- 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。
- 视图的规则和限制
下面是关于视图创建和使用的一些最常见的规则和限制。
- 与表一样,视图必须唯一命名(不能给视图取与别的视图或表相同的名字)。
- 对于可以创建的视图数目没有限制。
- 为了创建视图,必须具有足够的访问权限。这些限制通常由数据库管理人员授予。
- 视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造一个视图。
- ORDER BY可以用在视图中,但如果从该视图检索数据SELECT中也含有ORDER BY,那么该视图中的ORDER BY将被覆盖。
- 视图不能索引,也不能有关联的触发器或默认值。
- 视图可以和表一起使用。例如,编写一条联结表和视图的SELECT语句。
- 使用视图(CREATE VIEW)
视图用CREATE VIEW语句来创建。
- 使用SHOW CREATE VIEW viewname;来查看创建视图的语句。
- 用DROP删除视图,其语法为DROP VIEW viewname;。
- 更新视图时,可以先用DROP再用CREATE,也可以直接用CREATE OR REPLACE VIEW。如果要更新的视图不存在,则第2条更新语句会创建一个视图;如果要更新的视图存在,则第2条更新语句会替换原
有视图。
- 利用视图简化复杂的联结
mysql> create view empdept as select ename,dname,sal from emp left join dept on emp.deptno=dept.deptno where sal<2000;
Query OK, 0 rows affected (0.04 sec)
mysql> select * from empdept;
+--------+------------+---------+
| ename | dname | sal |
+--------+------------+---------+
| SMITH | RESEARCH | 800.00 |
| ALLEN | SALES | 1600.00 |
| WARD | SALES | 1250.00 |
| MARTIN | SALES | 1250.00 |
| TURNER | SALES | 1500.00 |
| ADAMS | RESEARCH | 1100.00 |
| JAMES | SALES | 950.00 |
| MILLER | ACCOUNTING | 1300.00 |
+--------+------------+---------+
8 rows in set (0.00 sec)
# 利用视图,可一次性编写基础的SQL,然后根据需要多次使用。
- 用视图重新格式化检索出的数据(Concat)
- 用视图过滤不想要的数据(WHERE子句)
- 使用视图与计算字段
- 更新视图
使用存储过程
- 存储过程
存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件,虽然它们的作用不仅限于批处理。
使用存储过程有3个主要的好处,即简单、安全、高性能。
- 执行存储过程(CALL)
- 创建存储过程(CREATE PROCEDURE productpricing())
- 删除存储过程(DROP PROCEDURE productpricing)
- 使用参数
- 建立智能存储过程......
- 检查存储过程
使用游标
- 游标
不像多数DBMS, MySQL游标只能用于存储过程(和函数)。