MySQL基础语句

SQL 是 Structure Query Language(结构化查询语言)的缩写,它是使用关系模型的数据库应用语言,由 IBM 在 20 世纪 70 年代开发出来,作为 IBM 关系数据库原型 System R 的原型关系语言,实现了关系数据库中的信息检索。

SQL 语句分类

SQL 语句主要可以分为以下几类:
DDL(Data Definition Languages,数据定义语言):定义了不同的数据段、数据库、表、列、索引等数据库对象。常用的语句关键字主要包括 create、drop、alter 等。
DML(Data Manipulation Language,数据操纵语言):用于添加、删除、更新和查询数据库记录,并检查数据完整性。常用的语句关键字主要包括 insert、delete、update 和 select 等。
DCL(Data Control Language,数据控制语句):用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括 grant、revoke 等。

DDL 语句

DDL 语句是数据定义语句的缩写。对数据库内部的对象进行创建、删除、修改等操作的语言。和 DML 语句的区别是:DML 只对表内部进行操作,而不涉及表的定义、结构的修改,更不会涉及其他对象。DDL 语句更多是有数据库管理员(DBA)使用,开发人员使用的不多。

创建数据库

  1. 启动 MySQL 服务后,输入以下命令 mysql -uCodePeak -p 连接到 MySQL 服务器:
codepeak@WINDSUN:~$ mysql -uCodePeak -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 34
Server version: 10.6.7-MariaDB-2ubuntu1.1 Ubuntu 22.04

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB>

此命令中,mysql 表示客户端命令,-u 后面跟连接的数据库用户,-p 表示需要输入的密码。成功登录后,会出现 MariaDB>。注:MariaDB 为 MySQL 的一个分支,使用上两者大同小异,暂不用关心细节。
下面的欢迎中说明了如下几部分内容:

  1. Mysql>提示符后面输入所要执行的 SQL 语句,用 ; 或者 \g 结束。按回车健执行。
  2. 客户端的连接 ID,这个数字记录了 MySQL 服务到目前为止的连接次数,每个连接会自动 +1,上面显示的是 34 次。
  3. MySQL 服务的版本,上面显示的是 10.6.7-MariaDB-2ubuntu1.1
  4. 通过 help; 或者 \h 命令来显示帮助内容。
  5. 通过 \c 命令来清楚命令行 buffer。
创建数据库库 CREATE
CREATE DATABASE dbname;

例如:

MariaDB> create database test1;
Query OK, 1 row affected (0.001 sec)

Query OK 表示上面的命令执行成功,这是 MySQL 的一个特点,所有的 DDL 和 DML 操作执行成功后都显示 “Query OK”。
1 row affected 表示 执行只影响了数据库中一行的记录。
0.001 sec 表示操作执行的耗时。
如果已经存在了此数据库,将会有如下错误:

MariaDB> create database test1;
ERROR 1007 (HY000): Can't create database 'test1'; database exists
查看数据库 SHOW DATABASES

如果你需要查看系统中都有那些数据库,可以用如下的命令查看:

MariaDB> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test1              |
+--------------------+
5 rows in set (0.001 sec)

可以发现,在上面的列表中,除了刚刚创建的 test1 外,还有 4 个数据库,他们都是安装 MySQL 时自动创建的,功能如下:
infomation_schema:主要存储了系统中的一些数据库对象信息,比如用户表信息、列信息、权限信息、字符集信息、分区信息等。
mysql:存储了系统的用户权限信息
performance_schema:主要用于收集数据库服务器性能参数。并且库里表的存储引擎均为PERFORMANCE_SCHEMA,而用户是不能创建存储引擎为 PERFORMANCE_SCHEMA 的表。MySQL 5.5 开始新增一个数据库。
sys:通常都是提供给专业的 DBA 人员排查一些特定问题使用的,其下所涉及的各项查询或多或少都会对性能有一定的影响,支持 MySQL 5.6 或更高版本,需要启用performance_schema,这里不过多介绍。

选择操作的数据库 USE dbname

例如要选择数据库 test1:

MariaDB> use test1;
Database changed
查看数据库中的表 SHOW TABLES
MariaDB> SHOW TABLES;
Empty set (0.001 sec)

应为刚创建的数据库没有表,所以命令结果为空。我们可以切换到 mysql 数据库,查看 mysql 数据库中表:

MariaDB> use mysql;
Database changed
MariaDB> show tables;
+---------------------------+
| Tables_in_mysql           |
+---------------------------+
| column_stats              |
| columns_priv              |
| db                        |
| event                     |
| func                      |
| general_log               |
| global_priv               |
| gtid_slave_pos            |
| help_category             |
| help_keyword              |
| ......             |
+---------------------------+
31 rows in set (0.001 sec)

删除数据库

DROP DATABASE dbname

删除数据库实例如下:

MariaDB> DROP DATABASE test1;
Query OK, 0 rows affected (0.038 sec)

操作成功后,提示 0 rows affected,这个可以不用关心,只需要提示 Query OK 就表示成功了。
注意:数据库删除后,下面的所有表数据都会全部删除,所有删除前一定要仔细检查并做好相应的备份。

创建表

在数据库中创建表的语法如下:

CREATE TABLE tablename (
	column_name_1 column_type_1 constraints,
	column_name_2 column_type_2 constraints,
  ...
	column_name_n column_type_n constraints,
);

数据库的表名是以目录的形式存在磁盘上,所以表名的字符可以是任何目录名允许的字符。
column_name_1 是列名,column_type_1 是列的数据类型,constraints 是这个列的约束条件,后面会讲。
例如:创建一个名称为 emp 的表。表中包括 ename(姓名)、hiredate(雇用日期)和 sal(薪水)3 个字段,字段类型分别为 varchar(10)、date、int(2)。关于字段类型之后再讲。

MariaDB> CREATE TABLE emp (
 	ename varchar(10),
 	hiredate date,
 	sal decimal(10, 2),
 	deptno int(2)
 );
Query OK, 0 rows affected (0.040 sec)

查看表定义

表创建完毕后,如果需要查看一下表的定义,可以使用如下命令:

DESC tablename;

例如:查看 emp 表,将输出如下信息:

MariaDB> DESC emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(10)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.002 sec)

虽然 desc 命令可以查看表的定义,但是其输出的信息还是不够全面,为了得到更全面的表定义信息,有时候就需要查看创建表的 SQL 语句,可以使用如下命令:

SHOW CREATE TABLE tablename \G;

将 emp 创建的表结构显示出来如下:

MariaDB> show create table emp \G;
*************************** 1. row ***************************
Table: emp
Create Table: CREATE TABLE `emp` (
`ename` varchar(10) DEFAULT NULL,
`hiredate` date DEFAULT NULL,
`sal` decimal(10,2) DEFAULT NULL,
`deptno` int(2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.000 sec)

ERROR: No query specified

除了可以看到表的 engine(存储引擎)和 charset(字符集)等信息。\G选项的含义是使得记录能够按照字段竖向排列,以便更好地显示内容较长得记录。

删除表

表的删除命令如下:

DROP TABLE tablename;

例如:删除数据库 emp:

MariaDB> DROP TABLE emp;
Query OK, 0 rows affected (0.040 sec)

修改表

  • 修改表的类型 (MODIFY)

对于已经创建好的表,可以对其修改表结构。使用 alter table 语句,语法如下:

ALTER TABLE tablename MODIFY [COLUMN] column_definition [FIRST | AFTER colname]

例如:修改 emp 表得 ename 字段,将 varchar(10) 改为 varchar(20):

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(10)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.002 sec)

MariaDB [test]> alter table emp modify ename varchar(20);
Query OK, 0 rows affected (0.042 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.002 sec)
  • 修改表的字段名 (CHANGE)
ALTER TABLE tablename CHANGE [COLUMN] old_col_name colunm_definition

例如:将 age 字段改名为 age1,同时修改字段类型为 int(4):

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age      | int(3)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.002 sec)

MariaDB [test]> alter table emp change age age1 int(4);
Query OK, 0 rows affected (0.040 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age1     | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.035 sec)

注意:change 和 modify 都可以修改表的定义。不同的是:changes 后面需要写两次列名,不太方便。但是 change 可以修改表的字段名,而 modify 不能。

  • 增加表字段 (ADD)

对于为创建好得表增加字段,可以使用如下语法:

ALTER TABLE tablename ADD [COLUMN] column_definition [FIRST | AFTER col_name]

例如,在表中新增加字段 age,类型为 int(3):

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.002 sec)

MariaDB [test]> alter table emp add column age int(3);
Query OK, 0 rows affected (0.042 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age      | int(3)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.002 sec)
  • 删除表字段 (DROP)

可以将已经创建的表的某个字段删除:

ALTER TABLE tablename DROP [COLUMN] col_name

例如,将 emp 表得 age 字段删除:

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age      | int(3)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.002 sec)

MariaDB [test]> alter table emp drop column age;
Query OK, 0 rows affected (0.042 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.002 sec)
  • 修改表的字段的排列顺序 ( [FIRST | AFTER] )

上面介绍的字段增加和修改的语法(ADD/CHANGE/MODIFY)中,都有一个可选项 [FIRST | AFTER colname] ,这个选项可以用来修改字段在表中的位置。
ADD 增加的字段默认是在表的最后位置,而 CHANGE/MODIFY 默认都不会改变字段的位置。
例如1:将新增加的字段 birth date 加在 ename 之后:

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age1     | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.002 sec)

MariaDB [test]> alter table emp add birth date after ename;
Query OK, 0 rows affected (0.040 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age1     | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
6 rows in set (0.002 sec)

例如2:修改字段 age,将它放在最前面:

Database changed
MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age      | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
6 rows in set (0.002 sec)

MariaDB [test]> alter table emp modify age int(3) first;
Query OK, 0 rows affected (0.041 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| age      | int(3)        | YES  |     | NULL    |       |
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
6 rows in set (0.002 sec)

注意:CHANGE/FIRST|AFGER COLUMN这些关键字是属于 MySQL 在标准 SQL 上的拓展,在其他数据库上不一定适用。

  • 更改表名 (RENAME)
ALTER TABLE tablename RENAME [TO] new tablename

例如:将表 emp 改名为 emp1:

MariaDB [test]> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| age      | int(3)        | YES  |     | NULL    |       |
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
6 rows in set (0.002 sec)

MariaDB [test]> alter table emp rename emp1;
Query OK, 0 rows affected (0.043 sec)

MariaDB [test]> desc emp;
ERROR 1146 (42S02): Table 'test.emp' doesn't exist
MariaDB [test]> desc emp1;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| age      | int(3)        | YES  |     | NULL    |       |
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+

DML 语句

DML 操作指的是对数据库表中记录的操作,主要包括表的记录的:

  1. 插入(insert)
  2. 更新(update)
  3. 删除(delete)
  4. 查询(select)

这是开发人员日常使用频繁的操作,下面一次进行介绍。

插入数据

插入记录的基本语法如下:

INSERT INTO tablename (field1, field2, ..., fieldn)
VALUES (value1, value2, ..., valuen);

例如:向表 emp 中插入以下记录:

MariaDB [test]> insert into emp (ename, hiredate, sal, deptno) value ('zzx1', '2022-01-01', '2000', 1);
Query OK, 1 row affected (0.034 sec)

也可以不使用指定字段名称,但是 values 后面的顺序必须和字段的排列顺序一致:

MariaDB [test]> insert into emp values('lisa', '2022-02-01', '3000', 2);
Query OK, 1 row affected (0.034 sec)

如果含可空字段、非空但有默认值字段、自增字段,可以不在 insert 后面的字段列表中出现,values 后面只写对应字段名称的值。这些没写字段自动设置为 NULL、默认值、自增值。
例如:只对 emp 表中的 ename 和 sal 字段显式插入值:

MariaDB [test]> insert into emp (ename, sal) values ('dony', 1000);
Query OK, 1 row affected (0.039 sec)

查看实际插入值如下:

MariaDB [test]> select * from emp;
+-------+------------+---------+--------+
| ename | hiredate   | sal     | deptno |
+-------+------------+---------+--------+
| zzx1  | 2022-01-01 | 2000.00 |      1 |
| lisa  | 2022-02-01 | 3000.00 |      2 |
| dony  | NULL       | 1000.00 |   NULL |
+-------+------------+---------+--------+
3 rows in set (0.001 sec)

可以看到,设置为可空的两个字段都显示为 NULL。
在 MySQL 中,insert 还有一个很好的特性,可以一次性插入多条记录,语法如下:

INSERT INTO tablename (field1, field2, ..., fieldn)
VALUES
(record1_value1, record1_value2, ..., record1_valuen),
(record2_value1, record2_value2, ..., record2_valuen),
...
(recordn_value1, recordn_value2, ..., recordn_valuen);

可以看出,每条记录之间都用逗号进行了分隔。
例如:对 dept 一次性插入两条记录:

MariaDB [test]> insert into dept values (5, 'dept5'), (6, 'dept6');
Query OK, 2 rows affected (0.035 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [test]> select * from dept;
+--------+----------+
| deptno | deptname |
+--------+----------+
|      5 | dept5    |
|      6 | dept6    |
+--------+----------+
2 rows in set (0.000 sec)

这个特性可以使得 MySQL 在插入大量记录时,节省很多网络开销,提高插入效率。

更新数据

表里的记录值可以通过 update 命令进行更改,语法如下:

UPDATE tablename SET field1=value1, field2=value2, ..., fieldn=valuen [WHERE CONDITION]

例如:将 emp 表中 ename 为 lisa 的薪水 sal 从 3000 更改到 4000:

MariaDB [test]> update emp set sal=4000 where ename='lisa';
Query OK, 1 row affected (0.034 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql update 命令可以同时更新多个表中的数据,语法如下:

UPDATE t1, t2, ..., tn SET t1.field1=expr1, ..., tn.fieldn=exprn [WHERE CONDITION]

例如:同时更新表 emp 中的字段 sal 和表 dept 中的字段 deptname:

MariaDB [test]> update emp a, dept b set a.sal=a.sal*b.septno, b.deptname=a.enmae where a.deptno=b.deptno;

注意:多表更新的语法更多的用于根据一个表的字段来动态地更新另一个表的字段。

删除数据

如果记录不再需要,则可以用 delete 命令进行删除,语法如下:

DELETE FROM tablename [WHERE CONDITION]

例如:将 emp 表中 ename 字段值为 dony 的记录全部删除:

MariaDB [test]> delete from emp where ename='dony';

在 MySQL 中可以一次删除多个表的数据,语法如下:

DELETE t1, t2, ..., tn FROM t1, t2, ..., tn [WHERE CONDITION]

如果 from 后面的表名用别名,则 delete后面也要用相应别名,否则会有语法错误。
例如:同时删除表 emp 和 dept 中 deptno 为 3 的记录:

MariaDB [test]> delete a, b from emp a, dept b where a.deptno=b.deptno and a.deptno=3;

注意:不管是单表还是多表,不加 where 条件将会把表的所有记录删除。

查询数据

使用 select 命令进行各种各样的查询,使得输出结果符合用户的要求。
SELECE 完整的语法比较复杂,先只介绍最基本的语法:

SELECT * FROM tablename [WHERE CONDITION]

最简单的方式是将记录全部选出。
例如:将表 emp 中的记录全部查询出来:

MariaDB [test]> select * from emp;

其中 * 表示将所有的记录都选出来,也可以用逗号分割所有字段来代替,例如:以下两个查询是等价的:

MariaDB [test]> select * from emp;
MariaDB [test]> select ename, hiredate, sal, deptno from emp;

*的好处是语法简单,但如果只需要部分字段时,还是需要将字段一个一个列出来。
查询时,还会遇到各种查询要求。

去重

如果需要将表中的记录去掉重复后显示出来,就可以用 distinct 关键字来实现:

MariaDB [test]> select distinct deptno from emp;
条件查询

很多时候,用户并不需要查询所有的记录,而是只需要根据限定条件来查询一部分数据,用 where 关键字可以实现这样的操作。
例如:查询所有 deptno 为 1 的记录:

MariaDB [test]> select * from emp where deptno=1;

where 后面除了 = 之外,还可以使用 > < >= <= !=等比较运算符,多个条件之间还可以使用 or 、and 等逻辑运算符进行多条件联合查询,运算符会在以后的章节中详细讲解。
例如:使用多字段条件查询:

MariaDB [test]> select * from emp where deptno=1 and sal<3000;
模糊查询

模糊查询主要用于搜索匹配字段中包含指定内容,主要用到了 MySQL 中的 LIKE 关键字,LIKE 是比较运算符中的一种,同时还有 REGEXP 运算符也是类似功能,这里先不赘述。
主要语句如下:

[NOT] LIKE '字符串'

其中:
NOT:可选参数,字段中的内容与指定的字符串不匹配时满足条件。
字符串:指定用来匹配的字符串。字符串可以是一个很完整的字符串,也可以包含通配符。
LILE 关键字支持两种通配符:

  1. % :代表任何长度的字符串,字符串的长度可以为 0。例如:a%b 表示以字母 a 开头,以字母 b 结尾的任意长度的字符串。该字符串可以代表 ab、acb、accb 等。
  2. _ :只能代表单个字符,字符的长度不能为 0。例如:a_b 可以代表 acb、adb、aub 等字符串。

注意:匹配的字符串必须加单引号或双引号。NOT LIKE 表示字符串不匹配时满足条件。

例如:查询 emp 表中 ename 字段所有以 zz 开头的记录:

MariaDB [test]> select * from emp;
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
| dony   | 2005-02-05 | 2000.00 |      4 |
| zzy    | 2005-02-06 | 3000.00 |      5 |
+--------+------------+---------+--------+
5 rows in set (0.001 sec)

MariaDB [test]> SELECT ename FROM emp WHERE ename LIKE 'zz%';
+-------+
| ename |
+-------+
| zzx   |
| zzy   |
+-------+
2 rows in set (0.001 sec)

例如:查询 emp 表中 ename 字段以 y 结尾,且 y 前面只有 3 个字母的记录:

MariaDB [test]> SELECT ename FROM emp WHERE ename LIKE '___y';
+-------+
| ename |
+-------+
| dony  |
+-------+
1 row in set (0.001 sec)

默认情况下,LIKE 关键字匹配字符的时候是不区分大小写的。如果需要区分大小写,可以加入 BINARY 关键字。
例如:

MariaDB [test]> SELECT ename FROM emp WHERE ename LIKE '%__Y';
+-------+
| ename |
+-------+
| dony  |
| zzy   |
| FYY   |
+-------+
3 rows in set (0.001 sec)

MariaDB [test]> SELECT ename FROM emp WHERE ename LIKE BINARY '%__Y';
+-------+
| ename |
+-------+
| FYY   |
+-------+
1 row in set (0.001 sec)

可以看到,加了 BINARY 后,Tom 和 Thomas 等记录就不会被匹配到了。
使用通配符的注意事项:

  1. 注意大小写。默认不区分大小写。
  2. 注意尾部空格。尾部空格会干扰通配符的匹配。例如:'T% ’ 就不能匹配到 ‘Tom’。
  3. 注意 NULL。% 通配符可以匹配到任意字符,但不能匹配到 NULL。
  4. 不要过度使用通配符,如果其他操作符能达到相同的目的。因为在对通配符处理时会花费更长的时间。
  5. 除非有绝对必要,否则不要把它们用在字符串的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
  6. 如果查询内容中包含通配符,可以使用转义符 \
排序

排序用关键字 ORDER BY 来实现,语法如下:

SELECT * FROM tablename [WHERE CONDITION] [ORDER BY field1 [DESC|ASC], field2 [DESC|ASC], ..., fieldn [DESC|ASC]]

其中,DESC 和 ASC 是排序顺序关键字, DESC 表示字段进行降序排列,ASC 表示升序排列,默认是升序排列。ORDER BY 后面可以跟多个不同的排序字段,并且每个排序字段可以有不同的排序顺序。
例如:把 emp 表中记录按照工资高低进行显示:

MariaDB [test]> select * from emp order by sal;

如果排序字段一样,则值相同的字段按照第二个字段进行排序,依次类推。如果只有一个排序字段,则这些字段相同的记录会无序排列。
例如:将 emp 表中按照部门编号 deptno 字段排序,如果 deptno 相同,按照工资由高到低排序:

select * from emp order by deptno, sal desc;
限制

对于排序后如果只希望显示一部分,而不是全部,可以使用 LIMIT 关键字来实现,LIMIT 关键字语法如下:

SELECT ... [LIMIT offset_start, row_count]

其中 offset_start 表示记录的起始偏移量, row_count 表示显示的行数。
默认情况下,offset_start 起始偏移量为 0,只需要写记录的行数就可以了,这时候就显示的是前 n 行记录。
例如:
显示 emp 表中按照 sal 排序后的前 3 条记录:

select * from emp order by sal limit 3;

如果 emp 表中按照 sal 排序后从第二条记录开始的 3 条记录,可以使用以下命令:

select * from emp order by sal limit 1, 3;

limit 经常和 order by 一起配合使用来进行记录的分页显示。

注意:limit 是 MySQL 拓展语法,在其他数据库上不能通用。

聚合

如果要进行一些汇总操作,比如统计整个公司的人数或者统计每个部门的人数,这时候就要用到 SQL 的聚合操作。
聚合操作语法如下:

SELECT [field1, field2, ..., fieldn] fun_name
FROM tablename
[WHERE where_condition]
GROUP BY field1, field2, ..., fieldn
[WITH ROLLUP]
[HAVING where_condition]

参数如下:
func_name:要做的聚合操作,也就是聚合函数,常用的有 sum、count、avg、max、min。
GROUP BY:表示关键字要进行分类聚合的字段,比如要按照部门分类统计员工数量。
WITH ROLLUP:是可选参数,表明是否对分类聚合后的结果进行再汇总。
HAVING:关键字表示对分类后的结果在进行条件的过滤。

注意:HAVING 和 WHERE 的区别:HAVING 是对聚合后的结果进行条件的过滤,而 WHERE 是在聚合前就对记录进行过滤。如果逻辑允许,尽可能用 WHERE 先过滤记录,因为这样结果集减小,聚合的效率大大提高,最后再根据逻辑看是否用 HAVING 进行再过滤。

例如:统计 emp 表中各个部门的人数

MariaDB [test]> select deptno, count(1) from emp group by deptno;

例如:既要统计各部门人数,又要统计总人数

MariaDB [test]> select deptno, count(1) from emp group by deptno with rollup;

统计人数大于 1 人的部门:

MariaDB [test]> select deptno, count(1) from emp group by deptno having count(1) > 1;

最后统计所有员工的薪水总额,最高和最低薪水:

MariaDB [test]> select sum(sal), max(sal), min(sal) from emp;
表连接

当需要同时显示多个表中的字段时,可以用表连接来实现。从大类上分,表的连接分为内连接和外连接,它们之间最主要的区别是:内连接仅选出两张表中最匹配的记录,而外连接会选出其他不匹配的记录。我们常用的是内连接。
例如:查询出所有雇员的名字和所在的部门名称。因为雇员名称和部门分别存放在表 emp 和 dept 中,因此需要使用表连接来进行查询:

MariaDB [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| dept           |
| emp            |
+----------------+
2 rows in set (0.001 sec)

MariaDB [test]> select * from emp;
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bjguan | 2004-04-02 | 5000.00 |      1 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
+--------+------------+---------+--------+
4 rows in set (0.001 sec)

MariaDB [test]> select * from dept;
+--------+----------+
| deptno | deptname |
+--------+----------+
|      1 | tech     |
|      2 | sale     |
|      3 | hr       |
+--------+----------+
3 rows in set (0.001 sec)

MariaDB [test]> select ename, deptname from emp, dept where emp.deptno=dept.deptno;
+--------+----------+
| ename  | deptname |
+--------+----------+
| zzx    | tech     |
| lisa   | sale     |
| bjguan | tech     |
| bzshen | hr       |
+--------+----------+
4 rows in set (0.001 sec)

表连接又分为左连接右连接,定义如下:

  • 左连接:包含所有左边表中的记录甚至是右边表中没有和它匹配的记录。
  • 右连接:包含所有右边表中的记录甚至是左边表中没有和它匹配的记录。

例如:查询 emp 中所有用户名所在部门名称:

MariaDB [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| dept           |
| emp            |
+----------------+
2 rows in set (0.001 sec)

MariaDB [test]> select * from emp;
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bjguan | 2004-04-02 | 5000.00 |      1 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
+--------+------------+---------+--------+
4 rows in set (0.001 sec)

MariaDB [test]> select * from dept;
+--------+----------+
| deptno | deptname |
+--------+----------+
|      1 | tech     |
|      2 | sale     |
|      3 | hr       |
+--------+----------+
3 rows in set (0.001 sec)

MariaDB [test]> select ename, deptname from emp left join dept on emp.deptno=dept.deptno;
+--------+----------+
| ename  | deptname |
+--------+----------+
| zzx    | tech     |
| bjguan | tech     |
| lisa   | sale     |
| bzshen | hr       |
| dony   | NULL     |
+--------+----------+
5 rows in set (0.001 sec)

比较这个查询和上例中的查询,区别在于本例中列出了所有的用户名,即使用户 dony 不存在合法的部门名称。
右连接和左连接类似,两者可以相互转换,例如上面的例子可以改写为如下的右连接:

MariaDB [test]> select ename, deptname from dept right join emp on dept.deptno=emp.deptno;
+--------+----------+
| ename  | deptname |
+--------+----------+
| zzx    | tech     |
| bjguan | tech     |
| lisa   | sale     |
| bzshen | hr       |
| dony   | NULL     |
+--------+----------+
5 rows in set (0.001 sec)
子查询

某些情况下,当进行查询时,需要的条件是 select 语句的结果,这时候,就要用到子查询。用于子查询的关键字主要包括:in、not in、=、!=、exists、not exists 等。
例如:从 emp 表中查询出所有部门在 dept 表中的所有记录:

MariaDB [test]> select * from emp;
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bjguan | 2004-04-02 | 5000.00 |      1 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
| dony   | 2005-02-05 | 2000.00 |      4 |
+--------+------------+---------+--------+
5 rows in set (0.001 sec)

MariaDB [test]> select * from dept;
+--------+----------+
| deptno | deptname |
+--------+----------+
|      1 | tech     |
|      2 | sale     |
|      3 | hr       |
|      5 | fin      |
+--------+----------+
4 rows in set (0.000 sec)

MariaDB [test]> select * from emp where deptno in (select deptno from dept);
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bjguan | 2004-04-02 | 5000.00 |      1 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
+--------+------------+---------+--------+
4 rows in set (0.001 sec)

如果子查询记录数唯一,还可以用 = 代替 in:

MariaDB [test]> select * from emp where deptno = (select deptno from dept);
ERROR 1242 (21000): Subquery returns more than 1 row
MariaDB [test]> select * from emp where deptno = (select deptno from dept limit 1);
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| bjguan | 2004-04-02 | 5000.00 |      1 |
+--------+------------+---------+--------+
2 rows in set (0.001 sec)

某些情况下,子查询可以转换为表连接,例如:

MariaDB [test]> select * from emp where deptno in (select deptno from dept);
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bjguan | 2004-04-02 | 5000.00 |      1 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
+--------+------------+---------+--------+

转换为表连接后:

MariaDB [test]> select emp.* from emp, dept where emp.deptno=dept.deptno;
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bjguan | 2004-04-02 | 5000.00 |      1 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
+--------+------------+---------+--------+

表连接在很多情况下用于优化子查询。

记录联合

我们通常会碰到这样的应用,将两个表的数据按照一定的查询条件查询出来后,将结果一起显示出来,这个时候,就需要用 union 和 union all 关键字来实现。
语法如下:

SELECT * FROM t1
UNION | UNION ALL
SELECT * FROM t2
...
UNION | UNION ALL
SELECT * FROM tn;

UNION 和 UNION ALL 的主要是 UNION ALL 是把结果集直接合并到一起,而 UNION 是将 UNION ALL 后的结果再进行一次 DISTINCT,去除重复记录后的结果。
例如:将 emp 和 dept 表中的部门编号的集合显示出来:

select * from emp;

将结果去掉重复记录后显示如下:

MariaDB [test]> select * from emp;
+--------+------------+---------+--------+
| ename  | hiredate   | sal     | deptno |
+--------+------------+---------+--------+
| zzx    | 2000-01-01 | 2000.00 |      1 |
| lisa   | 2003-02-01 | 4000.00 |      2 |
| bzshen | 2005-04-01 | 4000.00 |      3 |
| dony   | 2005-02-05 | 2000.00 |      4 |
+--------+------------+---------+--------+
4 rows in set (0.001 sec)

MariaDB [test]> select * from dept;
+--------+----------+
| deptno | deptname |
+--------+----------+
|      1 | tech     |
|      2 | sale     |
|      5 | fin      |
+--------+----------+
3 rows in set (0.000 sec)

MariaDB [test]> select deptno from emp
    -> union all
    -> select deptno from dept;
+--------+
| deptno |
+--------+
|      1 |
|      2 |
|      3 |
|      4 |
|      1 |
|      2 |
|      5 |
+--------+
7 rows in set (0.001 sec)

将结果去掉重复记录后显示如下:

MariaDB [test]> select deptno from emp
    -> union
    -> select deptno from dept;
+--------+
| deptno |
+--------+
|      1 |
|      2 |
|      3 |
|      4 |
|      5 |
+--------+
5 rows in set (0.001 sec)

DCL 语句

DCL 语句主要是 DBA 用来管理系统中对象权限时使用的,开发人员很少使用。
例如:创建一个数据库用户 user1,具有对 test 数据库中所有表的 SELECT/INSERT 权限:

MariaDB [test]> grant select, insert on sakila.* to 'user1'@'localhost' identified by '123';
Query OK, 0 rows affected (0.00 sec)

由于权限变更,需要将 user1 的权限变更,收回 INSERT,只能对数据库进行 SELECT 操作:

MariaDB [test]> revoke insert on sakila.* from 'user1'@'localhost';
Query OK, 0 rows affected (0.00 sec)

DCL 远不止这些操作,具体操作后面会有专讲。

MySQL 帮助

使用 mysql 时,可能会遇到如下问题:

  1. 某个操作忘记了,如何快速查找?
  2. 如何快速知道当前版本上某个字段类型的取值范围?
  3. 当前版本都支持哪些函数?
  4. 当前版本是否支持某个功能?

对于上面的这些问题,我们可以再 MySQL 官方文档中查,但是要消耗大量的时间和精力。

按照层次查看帮助

如果不知道帮助能提供什么,就可以用 ? contents 命令来显示所有可供查询的分类,如下:

MariaDB [(none)]> ? contents
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
   Account Management
   Administration
   Compound Statements
   Data Definition
   Data Manipulation
   Data Types
   Functions and Modifiers for Use with GROUP BY
   Functions
   Geographic Features
   Help Metadata
   Language Structure
   Plugins
   Procedures
   Sequences
   Table Maintenance
   Transactions
   User-Defined Functions
   Utility

对于列出的分类,可以使用 ? 类别名称 的方式针对用户感兴趣的内容进一步查看。
例如:想看看 MySQL 中都支持哪些数据类型,可以执行 ? data types 命令:

MariaDB [(none)]> ? data types
You asked for help about help category: "Data Types"
For more information, type 'help <item>', where <item> is one of the following
topics:
   AUTO_INCREMENT
   BIGINT
   BINARY
   BIT
   BLOB and TEXT Data Types
   BLOB
   BOOLEAN
   CHAR BYTE
   CHAR
   DATETIME

上面列出了此版本支持的所有数据类型,如果想知道 int 类型具体介绍,可以利用上面方法进一步查看:

MariaDB [(none)]> ? blob
Name: 'BLOB'
Description:
Syntax
------ 
BLOB[(M)]
 
Description
----------- 
A BLOB column with a maximum length of 65,535 (216 - 1)
bytes. Each
BLOB value is stored using a two-byte length prefix that
indicates the
number of bytes in the value.
...

通过 ? 这种方式,就可以一层一层的往下查找用户所关心的主题内容。

快速查阅帮助

在实际应用中,如果需要快速查阅某项语法时,可以使用关键字进行快速查询。
例如,想知道 insert 命令都能看到写什么:

MariaDB [(none)]> ? insert
Name: 'INSERT'
Description:
Syntax
------ 
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
 [INTO] tbl_name [PARTITION (partition_list)] [(col,...)]
 {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
 [ ON DUPLICATE KEY UPDATE
 col=expr
 [, col=expr] ... ]
...

快速查询元数据的信息

在日常工作中,我们经常会遇到类似下面的应用场景:

  1. 删除数据库 test1 下所有前缀为 tmp 的表。
  2. 将数据库 test1 下所有存储引擎为 myisam 的表改为 innodb。

对于这类需求,在 MySQL5.0 之前只能通过 show tables、show create table 或者 show table status 等命令来得到指定数据库下的表名和存储引擎,但通过这些命令显示的内容有限且不适合进行字符串的批量编辑。如果表很多,操作也很低效。
MySQL 5.0 后提供了一个新的数据库 information_schema,用来记录 Mysql 中的元数据。元数据指的是数据的数据,比如表名、列名、列类型、索引名等表的各种属性名称。
这个库比较特殊,是一个虚拟数据库,物理上并不存在相关的目录和文件,库里 show tables 显示的各种表也并不是实际存在的表,全部是视图。
对于上面的两种需求,可以简单的通过两个命令得到需要的 sql 语句:

select concat('drop table test1.', table_name, ';') from tables where table_schema='test1' and table_name like 'tmp%';
select concat('alter table test1.', table_name, 'engine=innodb;') from tables where table_schema='test1' and engine='MyISAM';

下面累出一些比较常用的视图:
SCHEMATA:该表提供了当前 MySQL 实例中所有数据库的信息,show databases 的结果取之此表。
TABLES:该表提供了关于数据库中的表的信息(包括视图),详细描述了某个表属于哪个 schema、表类型、表引擎、创建时间等信息。show tables from schemaname 的结果取之此表。
COLUMNS:该表提供了表中的列信息,详细描述了某张表的所有列以及每个列的信息。show clumns from shcemaname.tablename 的结果取之此表。
STATISTICS:该表提供了关于表索引的信息。show index from shcemaname.tablename 的结果取之此表。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code_peak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值