SQL入门到精通:玩转数据库的7大操作想轻松搞定数据库操作,却不知从何入手?SQL(结构化查询语言)作为数据库管理的“万能钥匙”,简单易学又功能强大,是每个技术爱好者必备的技能。本文将带你从零起步,通过7大核心操作,解锁SQL的奥秘——从基础概念到MySQL实战,无论是创建数据库、查询数据,还是优
想轻松搞定数据库操作,却不知从何入手?SQL(结构化查询语言)作为数据库管理的“万能钥匙”,简单易学又功能强大,是每个技术爱好者必备的技能。本文将带你从零起步,通过7大核心操作,解锁SQL的奥秘——从基础概念到MySQL实战,无论是创建数据库、查询数据,还是优化性能,都能一手掌握。让我们一起开启这场“玩转数据库”的旅程,轻松进阶SQL达人!
本文以“SQL入门到精通”为目标,浓缩7大数据库操作精华,带你快速上手SQL。内容涵盖SQL基础知识、MySQL入门技巧、数据定义、更新与查询方法、索引优化以及视图应用。通过通俗的讲解和实战代码示例,你将学会如何创建表、插入数据、高效检索信息,甚至用视图简化复杂操作。不管你是编程小白还是进阶玩家,这篇指南都能助你玩转数据库,提升技术硬实力!
SQL与关系数据库基本操作
结构化查询语言(Structured Query Language,SQL)是一种专门用来与数据库通信的语言,它可以帮助用户操作关系数据库。
SQL集数据查询(Data Query)、数据定义(Data Definition)、数据操纵(Data Manipulation)和数据控制(Data Control)四大功能于一体,其核心主要包含有以下几个部门:
MySQL是一个关系数据库管理系统(RDBMS),它具有客户/服务器体系结构 ,最初是由瑞典MySQL AB公司开发。
MySQL在SQL标准的基础上增加了部分扩展的语言要素:
SQL标准不提供修改数据库模式定义和修改视图定义的操作,用户如果需要修改这些对象,可先将它们删除然后再重建,或者也可以使用具体的关系数据库关系系统所提供的扩展语句来实现。
SQL标准没有提供索引相关的语句。
SQL标准提供的数据定义语句
操作对象 | 创建 | 删除 | 修改 |
---|---|---|---|
模式 | CREATE SCHEMA 语句 | DROP SCHEMA 语句 | |
表 | CREATE TABLE 语句 | DROP TABLE 语句 | ALTER TABLE 语句 |
视图 | CREATE VIEW 语句 | DROP VIEW 语句 |
CREATE {DATABASE|SCHEMA}[IF NOT EXISTS] db_name
[DEFAULT] CHARACTER SET [=] charset_name
|[DEFAULT] COLLATE [=] collation_name
此语法说明:
"[]" 标示其内容为可选项
"|" 用于分隔花括号中的选择项,表示可任选其中一项来与花括号外的语法成分共同组成SQL语句命令,即选项彼此间是“或”的关系
"db_name" 用于标示具体的数据库命名,且该数据库名必须符号操作系统文件夹命名规则,在MySQL中不区分大小写
"DEFAULT" 指定默认值
"CHARACTER SET" 指定数据库字符集(Charset)
"COLLATE" 指定字符集的校对规则
"IF NOT EXISTS" 用于在创建数据库前进行判断,只有该数据库目前尚不存在时才执行CREATE DATABASE操作,即此选项可以避免出现数据库已经存在而再新建的错误
在MySQL中创建一个名为mysql_test的数据库
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1370
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database if not exists mysql_test;
Query OK, 1 row affected (0.03 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| mysql_test |
| performance_schema |
| sys |
| win_pro |
| win_pro_test |
+--------------------+
7 rows in set (0.01 sec)
mysql>
USE db_name;
只有使用USE命令指定某个数据库为当前数据库之后,才能对该数据库及其存储的数据对象执行各种后续操作
ALTER {DATABASE | SCHEMA} [db_name]
alter_specification ...
修改已有数据库mysql_test的默认字符集和校对规则
mysql> use mysql_test;
Database changed
mysql> alter database mysql_test
-> default character set gb2312
-> default collate gb2312_chinese_ci;
Query OK, 1 row affected (0.02 sec)
mysql>
DROP {DATABASE|SCHEMA} [IF EXISTS] db_name
分别不使用和使用关键字”IF EXISTS“删除一个系统中尚未创建的数据库”mytest“
mysql> drop database mytest;
ERROR 1008 (HY000): Can't drop database 'mytest'; database doesn't exist
mysql> drop database if exists mytest;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql>
可选项”IF EXISTS“可以避免删除不存在的数据库时出现的MySQL错误信息。
使用DROP DATABASE 或 DROP SCHEMA 语句会删除指定的整个数据库,该数据库中的所有表(包括其中的数据)也将永久删除,因而使用该语句时,需谨慎,以免错误删除。
SHOW {DATABASES|SCHEMAS}
[LIKE 'pattern'|WHERE expr]
"LIKE" 匹配指定的数据库名称
"WHERE" 指定数据库名称查询范围的条件
使用SHOW DATABASES或SHOW SCHEMAS语句,只会列出当前用户权限范围内所能查看到的所有数据库名称。
列出当前用户可查看的数据库列表
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| mysql_test |
| performance_schema |
| sys |
| win_pro |
| win_pro_test |
+--------------------+
7 rows in set (0.00 sec)
mysql>
数据表是关系数据库中最重要、最基本的数据对象,也是数据存储的基本单位。
数据表被定义为字段的集合,数据在表中是按照行和列的格式来存储的,每一行代表一条记录,每一列代表记录中一个字段的取值。
创建数据表的过程,实质上就是定义每个字段的过程,同时也是实施数据完整性约束的过程。
CREATE [TEMPORARY] TABLE tbl_name
(
字段名1 数据类型 [列级完整性约束条件] [默认值]
[, 字段名2 数据类型 [列级完整性约束条件] [默认值]]
[, ......]
[, 表级完整性约束条件]
) [ENGINE=引擎类型];
在一个已有数据库mysql_test中新建一个包含客户姓名、性别、地址、联系方式等内容的客户基本信息表,要求将客户的id号指定为该表的主键。
mysql> use mysql_test;
Database changed
mysql> create table customers
-> (
-> cust_id int not null auto_increment,
-> cust_name char(50) not null,
-> cust_sex char(1) not null default 0,
-> cust_address char(50) null,
-> cust_contact char(50) null,
-> primary key (cust_id)
-> );
Query OK, 0 rows affected (0.04 sec)
mysql> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| customers |
+----------------------+
1 row in set (0.01 sec)
mysql>
向数据库mysql_test的表customers中添加一列,并命名为cust_city,用于描述用户所在的城市,要求其不能为NULL,默认值为字符串’Wuhan‘,且该列位于原表cust_sex列之后
mysql> alter table mysql_test.customers
-> add column cust_city char(10) not null default 'Wuhan' after cust_sex;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(50) | NO | | NULL | |
| cust_sex | char(1) | NO | | 0 | |
| cust_city | char(10) | NO | | Wuhan | |
| cust_address | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql>
将数据库mysql_test中表customers的cust_sex列重命名为sex,且将其数据类型更改为字符长度为1的字符数据类型char(1),允许其为NULL,默认值为字符常量’M‘
mysql> alter table mysql_test.customers
-> change column cust_sex sex char(1) null default 'M';
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(50) | NO | | NULL | |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Wuhan | |
| cust_address | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
mysql>
将数据库mysql_test中表customers的cust_city列的默认值修改为字符常量’Beijing‘
mysql> alter table mysql_test.customers
-> alter column cust_city set default 'Beijing';
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(50) | NO | | NULL | |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
mysql>
将数据库mysql_test中表customers的cust_name列的数据类型由之前的字符长度为50的定长字符数据类型char(50)更改为字符长度为20的定长字符数据类型char(20),并将此列设置成表的第一列。
mysql> alter table mysql_test.customers
-> modify column cust_name char(20) first;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_name | char(20) | YES | | NULL | |
| cust_id | int | NO | PRI | NULL | auto_increment |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
mysql>
删除数据库mysql_test中表custmoers的 cust_contact列
mysql> alter table mysql_test.customers
-> drop column cust_contact;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_name | char(20) | YES | | NULL | |
| cust_id | int | NO | PRI | NULL | auto_increment |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
mysql>
使用RENAME [TO] 子句,重命名数据库mysql_test中表customers的表名为backup_customers
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| mysql_test |
| performance_schema |
| sys |
| win_pro |
| win_pro_test |
+--------------------+
7 rows in set (0.01 sec)
mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| customers |
+----------------------+
1 row in set (0.00 sec)
mysql> alter table mysql_test.customers
-> rename to mysql_test.backup_customers;
Query OK, 0 rows affected (0.02 sec)
mysql> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| backup_customers |
+----------------------+
1 row in set (0.00 sec)
mysql>
用RENAME TABLE 语句来更改表的名字,并可同时重命名多个表
RENAME TABLE tbl_name TO new_tal_name
[, tbl_name2 TO new_tbl_name2] ...
使用RENAME TABLE 语句,将表backup_customers命名为customers
mysql> rename table mysql_test.backup_customers to mysql_test.customers;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| customers |
+----------------------+
1 row in set (0.00 sec)
mysql>
DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name [, tbl_name] ...
[RESTRICT | CASCADE]
DROP TABLE 语句可以同时删除多个表(包括临时表),但操作者必须拥有该命令的权限
当表被删除时,其中存储的数据和分区信息均会被删除,所以使用该语句须格外小心,但操作者在该表上的权限并不会自动被删除
(1)显示表的名称
SHOW [FULL] TABLES [{FROM | IN} db_name]
[LIKE 'pattern' | WHERE expr]
显示数据库mysql_test中所有的表名
mysql> use mysql_test;
Database changed
mysql> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| customers |
+----------------------+
1 row in set (0.00 sec)
mysql>
(2)显示表的结构
第一种
SHOW [FULL] COLUMNS {FROM | IN} tbl_name [{FROM | IN} db_name]
[LIKE 'pattern' | WHERE expr]
第二种
{DESCRIBE | DESC} tbl_name [col_name | wild]
说明:MySQL支持用DESCRIBE 作为 SHOW COLUMNS FROM 的一种快捷方式
显示数据库mysql_test中表customers的结构
mysql> desc mysql_test.customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_name | char(20) | YES | | NULL | |
| cust_id | int | NO | PRI | NULL | auto_increment |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql>
索引是DBMS根据表中的一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表,因而索引实质上是一张描述索引列的列值与原表中记录行之间一一对应关系的有序表。
索引是提高数据文件访问效率的有效方法。
1)索引是以文件的形式存储的,DBMS会将一个表的所有索引保存在同一个索引文件中,索引文件需要占用磁盘空间。
2)索引在提供查询速度的同时,却会降低更新表的速度。表中的索引越多,则更新表的时间就会越长。
单列索引:一个索引只包含原表中的一个列
组合索引:也称复合索引或多列索引,就是原表中多个列共同组成一个索引
一个表可以有多个单列索引,但这些索引不是组合索引
按照最左前缀的法则,一个组合索引实质上为表的查询提供了多个索引,以此来加快查询速度
CREATE [UNIQUE] INDEX index_name
ON tbl_name (index_col_name, ...)
其中,index_col_name的格式为:
col_name [(length)][ASC | DESC]
可选项”UNIQUE“关键字用于指定创建唯一性索引
”Index_name“用于指定索引名,一个表可以创建多个索引,但每个索引在该表中的名称必须是唯一的
”tbl_name"用于指定要建立索引的表名
“Index_col_name”是关于索引列的描述
例子:在数据库mysql_test 的表customers 上,根据客户姓名列的前三个字符创建一个升序索引 index_customers
mysql> create index index_customers
-> on mysql_test.customers(cust_name(3) asc);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from mysql_test.customers;
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| customers | 0 | PRIMARY | 1 | cust_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
| customers | 1 | index_customers | 1 | cust_name | A | 0 | 3 | NULL | YES | BTREE | | | YES | NULL |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.00 sec)
mysql>
例子:在数据库mysql_test的表customers 上,根据客户姓名列和客户id号创建一个组合索引 index_cust
mysql> create index index_cust
-> on mysql_test.customers(cust_name, cust_id);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from mysql_test.customers;
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| customers | 0 | PRIMARY | 1 | cust_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
| customers | 1 | index_customers | 1 | cust_name | A | 0 | 3 | NULL | YES | BTREE | | | YES | NULL |
| customers | 1 | index_cust | 1 | cust_name | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL |
| customers | 1 | index_cust | 2 | cust_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
4 rows in set (0.01 sec)
mysql>
例子:在已有数据库mysql_test上新建一个包含产品卖家id号、姓名、地址、联系方式、售卖产品类型、当月销量等内容的产品卖家信息表 seller,要求在创建表的同时,为该表添加由卖家id号和售卖产品类型组成的联合主键,并在当月销量上创建索引
mysql> use mysql_test;
Database changed
mysql> create table seller
-> (
-> seller_id int not null auto_increment,
-> seller_name char(50) not null,
-> seller_address char(50) null,
-> seller_contact char(50) null,
-> product_type int(5) null,
-> sales int null,
-> primary key (seller_id, product_type),
-> index index_seller(sales)
-> );
ERROR 1171 (42000): All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead
mysql>
这个例子说明:MySQL可以在一个表上同时创建多个索引,并且使用 PRIMARY KEY 的列必须是一个具有 NOT NULL属性的列
mysql> create table seller
-> (
-> seller_id int not null auto_increment,
-> seller_name char(50) not null,
-> seller_address char(50) null,
-> seller_contact char(50) null,
-> product_type int(5) not null,
-> sales int null,
-> primary key (seller_id, product_type),
-> index index_seller(sales)
-> );
Query OK, 0 rows affected, 1 warning (0.02 sec)
mysql> desc mysql_test.seller;
+----------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+----------+------+-----+---------+----------------+
| seller_id | int | NO | PRI | NULL | auto_increment |
| seller_name | char(50) | NO | | NULL | |
| seller_address | char(50) | YES | | NULL | |
| seller_contact | char(50) | YES | | NULL | |
| product_type | int | NO | PRI | NULL | |
| sales | int | YES | MUL | NULL | |
+----------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
mysql>
例子:使用 ALTER TABLE 语句在数据库 mysql_test 中表 seller的姓名列上添加一个非唯一的索引,取名为 index_seller_name
mysql> alter table mysql_test.seller
-> add index index_seller_name(seller_name);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from mysql_test.seller;
+--------+------------+-------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+-------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| seller | 0 | PRIMARY | 1 | seller_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
| seller | 0 | PRIMARY | 2 | product_type | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
| seller | 1 | index_seller | 1 | sales | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL |
| seller | 1 | index_seller_name | 1 | seller_name | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
+--------+------------+-------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
4 rows in set (0.00 sec)
mysql>
SHOW {INDEX | INDEXES | KEYS}
{FROM | IN} tbl_name
[{FROM | IN} db_name]
[WHERE expr]
DROP INDEX index_name ON tbl_name
例子:删除 customers表创建的索引 index_cust
mysql> show index from mysql_test.customers;
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| customers | 0 | PRIMARY | 1 | cust_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
| customers | 1 | index_customers | 1 | cust_name | A | 0 | 3 | NULL | YES | BTREE | | | YES | NULL |
| customers | 1 | index_cust | 1 | cust_name | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL |
| customers | 1 | index_cust | 2 | cust_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
4 rows in set (0.00 sec)
mysql> drop index index_cust on mysql_test.customers;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from mysql_test.customers;
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| customers | 0 | PRIMARY | 1 | cust_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
| customers | 1 | index_customers | 1 | cust_name | A | 0 | 3 | NULL | YES | BTREE | | | YES | NULL |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.00 sec)
mysql>
例子:使用 ALTER TABLE 语句删除数据库 mysql_test 中表 customers 的主键和索引 index_customers
# 删除索引报错
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
# 解决:修改为唯一约束
mysql> alter table mysql_test.customers add unique(cust_id);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> alter table mysql_test.customers drop primary key, drop index index_customers;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from mysql_test.customers;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| customers | 0 | cust_id | 1 | cust_id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.00 sec)
INSERT [INTO] tbl_name [(col_name, ...)]
{VALUES | VALUE} ({expr | DEFAULT}, ...), (...), ...
例子:使用 INSERT...VALUES 语句向数据库 mysql_test 的表 customers 中插入这样一行完整数据:(901,张三,F,北京市,朝阳区)
mysql> insert into mysql_test.customers
-> values (901,'张三','F','北京市','朝阳区');
ERROR 1366 (HY000): Incorrect integer value: '张三' for column 'cust_id' at row 1
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_name | char(20) | YES | | NULL | |
| cust_id | int | NO | PRI | NULL | auto_increment |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> alter table mysql_test.customers modify cust_name char(20) after cust_id;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(20) | YES | | NULL | |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
mysql> insert into mysql_test.customers values (901,'张三','F','北京市','朝阳区');
Query OK, 1 row affected (0.00 sec)
mysql> select * from customers;
+---------+-----------+------+-----------+--------------+
| cust_id | cust_name | sex | cust_city | cust_address |
+---------+-----------+------+-----------+--------------+
| 901 | 张三 | F | 北京市 | 朝阳区 |
+---------+-----------+------+-----------+--------------+
1 row in set (0.00 sec)
mysql>
例子:使用 INSERT...VALUES 语句向数据库 mysql_test 的表 customers 中插入一行数据,要求该数据目前只用明确给出cust_name列和cust_address列的信息,即分别为“李四”和“武汉市”,而cust_id列的值由系统自动生成,cust_sex列选用表中默认值,另外cust_contact列的值暂不确定,可不用指定。
mysql> insert into mysql_test.customers values(0,'李四',default,'武汉市',null);
Query OK, 1 row affected (0.01 sec)
mysql> select * from customers;
+---------+-----------+------+-----------+--------------+
| cust_id | cust_name | sex | cust_city | cust_address |
+---------+-----------+------+-----------+--------------+
| 901 | 张三 | F | 北京市 | 朝阳区 |
| 902 | 李四 | M | 武汉市 | NULL |
+---------+-----------+------+-----------+--------------+
2 rows in set (0.00 sec)
为了编写更为安全的 INSERT...VALUES 语句,通常需要在表名后的括号中明确地给出列名清单
mysql> insert into mysql_test.customers(cust_id,cust_name,cust_sex,cust_address,cust_contact)
-> values(0,'李四',default,'武汉市',null);
ERROR 1054 (42S22): Unknown column 'cust_sex' in 'field list'
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(20) | YES | | NULL | |
| sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
mysql> alter table mysql_test.customers change column sex cust_sex char(1) null default 'M';
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> insert into mysql_test.customers(cust_id,cust_name,cust_sex,cust_address,cust_contact) values(0,'李四',default,'武汉市',null);
ERROR 1054 (42S22): Unknown column 'cust_contact' in 'field list'
mysql> alter table mysql_test.customers
-> add column cust_contact char(50) null;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(20) | YES | | NULL | |
| cust_sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql> insert into mysql_test.customers(cust_id,cust_name,cust_sex,cust_address,cust_contact) values(0,'李四',default,'武汉市',null);
Query OK, 1 row affected (0.00 sec)
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 朝阳区 | NULL |
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
3 rows in set (0.00 sec)
mysql>
INSERT [INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
例子:
mysql> insert into mysql_test.customers
-> set cust_name='李四',cust_address='武汉市',cust_sex=DEFAULT;
Query OK, 1 row affected (0.00 sec)
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 朝阳区 | NULL |
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
4 rows in set (0.00 sec)
mysql>
INSERT [INTO] tbl_name [(col_name, ...)]
SELECT ...
SELECT 子句返回的是一个查询到的结果集
DELETE FROM tbl_name
[WHERE wherr_condition]
[ORDER BY ...]
[LIMIT row_count]
例子:使用DELETE 语句删除数据库 mysql_test 的表 customers 中客户名为“王五”的客户信息
mysql> insert into mysql_test.customers set cust_name='王五',cust_address='武汉市',cust_sex=DEFAULT;
Query OK, 1 row affected (0.00 sec)
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 朝阳区 | NULL |
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
| 905 | 王五 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
5 rows in set (0.00 sec)
mysql> delete from mysql_test.customers
-> where cust_name='王五';
Query OK, 1 row affected (0.00 sec)
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 朝阳区 | NULL |
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
4 rows in set (0.00 sec)
mysql>
UPDATE tbl_name
SET col_name={expr|DEFAULT}[,col_name2={expr|DEFAULT}]...
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
例子:使用 UPDATE 语句将数据库 mysql_test 的表 customers 中姓名为“张三”的客户的地址更新为“武汉市”
mysql> update mysql_test.customers
-> set cust_address='武汉市'
-> where cust_name='张三';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 武汉市 | NULL |
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
4 rows in set (0.00 sec)
mysql>
SELECT
[ALL | DISTINCT | DISTINCTROW]
select_expr [,select_expr ...]
FROM table_references
[WHERE where_condition]
[GROUP BY {col_name|expr|position}
[ASC|DESC],...[WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name|expr|position}
[ASC|DESC],...]
[LIMIT {[offset,]row_count|row_count OFFSET offset}]
子句 | 说明 | 是否必须使用 |
---|---|---|
SELECT | 要返回的列或表达式 | 是 |
FROM | 从中检索数据的表 | 仅在从表选择数据时使用 |
WHERE | 行级过滤 | 否 |
GROUP BY | 分组说明 | 仅在按组计算聚合时使用 |
HAVING | 组级过滤 | 否 |
ORDER BY | 输出排序顺序 | 否 |
LIMIT | 要检索的行数 | 否 |
在 SELECT 语句中,语法项”select_expr“主要用于指定需要查询的内容,其指定方法通常有以下几种:
例子:查询数据库mysql_test的表customers中各个客户的姓名、性别和地址信息
mysql> select cust_name,cust_sex,cust_address
-> from mysql_test.customers;
+-----------+----------+--------------+
| cust_name | cust_sex | cust_address |
+-----------+----------+--------------+
| 张三 | F | 武汉市 |
| 李四 | M | NULL |
| 李四 | M | 武汉市 |
| 李四 | M | 武汉市 |
+-----------+----------+--------------+
4 rows in set (0.00 sec)
mysql>
例子:查询数据库mysql_test的表customers中各个客户的所有信息
mysql> select * from mysql_test.customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 武汉市 | NULL |
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
4 rows in set (0.00 sec)
mysql>
将SELECT语句的语法项”select_expr“指定为如下语法格式:
column_name [AS] column_alias
例子:查询数据库mysql_test的表customers中客户的cust_name列、cust_address列和cust_contact,要求将结果集中cust_address列的名称使用别名”地址“替代
mysql> select cust_name,cust_address as 地址,cust_contact
-> from mysql_test.customers;
+-----------+-----------+--------------+
| cust_name | 地址 | cust_contact |
+-----------+-----------+--------------+
| 张三 | 武汉市 | NULL |
| 李四 | NULL | NULL |
| 李四 | 武汉市 | NULL |
| 李四 | 武汉市 | NULL |
+-----------+-----------+--------------+
4 rows in set (0.00 sec)
mysql>
将SELECT语句的语法项”select_expr“指定为如下语法格式:
CASE
WHERE 条件1 THEN 表达式1
WHERE 条件2 THEN 表达式2
...
ELSE 表达式
END[AS] colunm_alias
例子:查询数据库mysql_test的表customers中客户的cust_name列和cust_sex列,要求判断结果集中cust_sex列的值,如果该列的值为M,则显示输出”男“,否则为”女“,同时在结果集的显示中奖cust_sex列用别名”性别“标注
mysql> select cust_name,
-> case
-> when cust_sex='M' then '男'
-> else '女'
-> end as 性别
-> from mysql_test.customers;
+-----------+--------+
| cust_name | 性别 |
+-----------+--------+
| 张三 | 女 |
| 李四 | 男 |
| 李四 | 男 |
| 李四 | 男 |
+-----------+--------+
4 rows in set (0.00 sec)
mysql>
例子:查询数据库 mysql_test 的表 customers 中每个客户的 cust_name 列、cust_sex列,以及对cust_id列加上数字100后的值
mysql> select cust_name,cust_sex,cust_id+100
-> from mysql_test.customers;
+-----------+----------+-------------+
| cust_name | cust_sex | cust_id+100 |
+-----------+----------+-------------+
| 张三 | F | 1001 |
| 李四 | M | 1002 |
| 李四 | M | 1003 |
| 李四 | M | 1004 |
+-----------+----------+-------------+
4 rows in set (0.00 sec)
聚合函数通常是数据库系统中一类系统内置函数,常用于对一组值进行计算,然后返回单个值。
除COUNT函数外,聚合函数都会忽略空值。
MySQL中常用聚合函数表
函数名 | 说明 |
---|---|
COUNT | 求组中项数,返回INT类型整数 |
MAX | 求最大值 |
MIN | 求最小值 |
SUM | 返回表达式中所有值的和 |
AVG | 求组中值的平均値 |
STD 或 STDDEV | 返回给定表达式中所有值的标准值 |
VARIANCE | 返回给定表达式中所有值的方差 |
GROUP_CONCAT | 返回由属于一组的列值连接组合而成的结果 |
BIT_AND | 逻辑或 |
BIR_OR | 逻辑与 |
BIT_XOR | 逻辑异或 |
若一个查询同时涉及两个或两个以上的表,则称之为多表连接查询,也称多表查询或连接查询。
多表连接查询是关系数据库中最主要的查询。
通过在FROM子句中指定多个表时,SELECT操作会使用“连接”运算将不同表中需要查询的数据组合到一个结果集中,并同样以一个临时表的形式返回,其连接方式主要包括交叉连接、内连接和外连接。
例子:假设数据库中有两张表,分别是 tbl1 和tbl2,现要求输出这两张表执行交叉联接后的所有数据集
mysql> SELECT * FROM tbl1 CROSS JOIN tbl2;
mysql> SELECT * FROM tbl1,tbl2;
SELECT some_columns
FROM table1
INNER JOIN
table2
ON some_conditions;
连接条件“some_sonditions”一般使用的语法格式是:
[<table1>.]<列名或列别名><比较运算符>[<table2>.]<列名或列别名>
示例:
mysql> SELECT * FROM tb_student INNER JOIN tb_score ON tb_student.studentNo = tb_score.studentNo;
在FROM子句中使用关键字“INNER JOIN” 或 “JOIN”连接两张表时,如若在ON子句的连接条件中使用运算符 “=”(即等号),即进行相等性测试,则此连接方式称为等值连接,也称为相等连接。通常,在等值连接的条件设置中会包含一个主键和一个外键。
在FROM子句中使用关键字“INNER JOIN” 或 “JOIN”连接两张表时,如若在ON子句的连接条件中使用除运算符 “=”之外的其他比较运算符,即进行不相等性测试,则此连接方式称为非等值连接,也称为不等连接。
在FROM子句中使用关键字“INNER JOIN” 或 “JOIN”连接两张表时,可以将一个表与它自身进行连接,这种连接方式称为自连接。
自连接时一种特殊的内连接,若需要在一个表中查找具有相同列值的行,则可以考虑使用自连。
使用自连接时,需要为表指定两个不同的别名,且对所有查询列的引用均必须使用表别名限定,否则SELECT操作会失败。
外连接是首先将连接的两张表分为基表和参考表,然后再以基表为依据返回满足和不满足条件的记录。
外连接可以在表中没有匹配记录的情况下仍返回记录。
左外连接,也称左连接,它的使用语法格式与内连接大致相同,区别仅在于它在 FROM 子句中使用关键字 “LEFT OUTER JOIN” 或关键字 “LEFT JOIN" 来连接两张表,而不是使用关键字 ”INNER JOIN“ 或 ”JOIN“,如此可用于接收关键字 ”LEFT OUTER JOIN“ 或 ”LEFT JOIN“ 左边表(也称为基表)的所有行,并用这些行与该关键字右边表(也称为参考表)中的行进行匹配,即匹配左表中的每一行及右表中符号条件的行。
左外连接的结果集中的NULL值表示右表中没有找到与左表相符的记录
右外连接,也称右连接,它的使用语法格式与内连接大致相同,区别仅在于它在 FROM 子句中使用关键字 ”RIGHT OUTER JOIN“ 或关键字 ”RIGHT JOIN“ 来连接两张表,而不是使用关键字 ”INNER JOIN“ 或 ”JOIN“。
右外连接是以右表为基表,其连接方式与左外连接完全一样。
在右外连接的结果集中除了匹配的行之外,还包括右表中有的,但在左表中不匹配的行,对于这样的行,从左表中被选择的列的值被设置为NULL。
左外连接例子:
mysql> SELECT * FROM tb_student LEFT JOIN tb_score ON tb_student.studentNo = tb_score.studentNo;
WHERE 子句中设置过滤条件的几个常用方法:
比较运算符表
比较运算符 | 说明 |
---|---|
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
<=> | 不会返回 UNKNOWN |
例子:在数据库 mysql_test 的表 customers 中查找所有男性客户的信息
mysql> select * from mysql_test.customers where cust_sex = 'M';
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
3 rows in set (0.00 sec)
mysql>
(1) BETWEEN...AND
expression [NOT] BETWEEN expression1 AND expression2
在数据库mysql_test 的表 customers 中,查询客户 id号在903至912之间的十个客户信息
mysql> select * from mysql_test.customers where cust_id between 903 and 912;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
2 rows in set (0.00 sec)
mysql>
(2)IN
expression IN (expression [,...n])
例子:在数据库 mysql_test 的表 customers 中,查询客户id号分别为903、906和908三个客户的信息
mysql> select * from mysql_test.customers where cust_id in (903,906,908);
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
1 row in set (0.00 sec)
mysql>
expression IS [NOT] NULL
例子:在数据库mysql_test的表customers中,查询是否存在没有填写客户联系方式的客户
mysql> select cust_name from mysql_test.customers where cust_contact is null;
+-----------+
| cust_name |
+-----------+
| 张三 |
| 李四 |
| 李四 |
| 李四 |
+-----------+
4 rows in set (0.01 sec)
mysql>
通常,可以使用 SELECT 语句创建子查询,即可嵌套在其他SELECT查询中的SELECT查询。
在MySQL中,区分如下四类子查询:
expression [NOT] IN (subquery)
例子:根据学生基本信息登记表 tb_student 和学生成绩表 tb_score,使用子查询的方式查询任意所选课程成绩高于80分的学生的学号和姓名信息
mysql> SELECT studentNo, studentName FROM tb_student WHERE studentNo IN (SELECT studentNo FROM tb_score WHERE score>80);
expression {=|<|<=|>|>=|<=>|<>|!=} {ALL|SOME|ANY} (subquery)
EXIST (subquery)
GROUP BY {col_name|expr|position}[ASC|DESC],...[WITH ROLLUP]
例子:在数据库 mysql_test 的表 customers 中获取一个数据结果集,要求改结果集中分别包含每个相同地址的男性客户人数和女性客户人数
mysql> select cust_address, cust_sex, count(*) as '人数'
-> from mysql_test.customers
-> group by cust_address,cust_sex;
+--------------+----------+--------+
| cust_address | cust_sex | 人数 |
+--------------+----------+--------+
| 武汉市 | F | 1 |
| NULL | M | 1 |
| 武汉市 | M | 2 |
+--------------+----------+--------+
3 rows in set (0.00 sec)
mysql>
例子2:在数据库 mysql_test 的表 customers 中获取一个数据结果集,要求该结果集中包含每个相同地址的男性客户人数、女性客户人数、总人数以及客户的总人数
mysql> select cust_address,cust_sex,count(*) as '人数'
-> from mysql_test.customers
-> group by cust_address,cust_sex
-> with rollup;
+--------------+----------+--------+
| cust_address | cust_sex | 人数 |
+--------------+----------+--------+
| NULL | M | 1 |
| NULL | NULL | 1 |
| 武汉市 | F | 1 |
| 武汉市 | M | 2 |
| 武汉市 | NULL | 3 |
| NULL | NULL | 4 |
+--------------+----------+--------+
6 rows in set (0.00 sec)
mysql>
HAVING where_condition
HAVING 子句与 WHERE 子句非常相似,HAVING 子句支持 WHERE 子句中所有的操作符和句法,但两者之间仍存在以下几点差异:
例子:在数据库 mysql_test 的表 customers 中查找这样一类客户信息:要求在返回的结果集中,列出相同客户地址中满足客户人数少于3的所有客户姓名及其对应地址。
mysql> select cust_name,cust_address
-> from mysql_test.customers
-> group by cust_address,cust_name
-> having count(*) <=3;
+-----------+--------------+
| cust_name | cust_address |
+-----------+--------------+
| 张三 | 武汉市 |
| 李四 | NULL |
| 李四 | 武汉市 |
+-----------+--------------+
3 rows in set (0.01 sec)
mysql>
ORDER BY {col_name | expr | position} [ASC | DESC],...
例子:在数据库 mysql_test 的表 customers 中依次按照客户姓名和地址的降序方式,输出客户的姓名和性别。
mysql> select cust_name,cust_sex from mysql_test.customers
-> order by cust_name desc,cust_address desc;
+-----------+----------+
| cust_name | cust_sex |
+-----------+----------+
| 张三 | F |
| 李四 | M |
| 李四 | M |
| 李四 | M |
+-----------+----------+
4 rows in set (0.01 sec)
mysql>
ORDER BY 子句 | GROUP BY 子句 |
---|---|
排序产生的输出 | 分组行,但输出可能不是分组的排序 |
任意列都可以使用 | 只可能使用选择列或表达式列 |
不一定需要 | 若与聚合函数一起使用列或表达式,则必须使用 |
LIMIT {[offset,] row_count | row_count OFFSET offset}
例子:在数据库 mysql_test 的表 customers 中查找从第5位客户开始的3位客户的id号和姓名信息
mysql> select cust_id,cust_name from mysql_test.customers
-> order by cust_id
-> limit 4,3;
Empty set (0.00 sec)
mysql> select cust_id,cust_name from mysql_test.customers
-> order by cust_id
-> limit 3 offset 4;
Empty set (0.01 sec)
mysql>
外模式对应到数据库中的概念就是视图(View)。
视图是数据库中的一个对象,它是数据库管理系统提供给用户的以多种角度观察数据库中数据的一种重要机制。
视图是从一个或多个表或者其他视图中通过查询语句导出的表,它也包含一系列带有名称的数据列和若干条数据行,并有自己的视图名,由此可见视图与基本表十分类似。
视图与数据库中真实存在的基本表存在以下区别:
视图的优点:
CREATEVIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
例子:在数据库mysql_test 中创建视图 customers_view,要求该视图包含客户信息表 customers 中所有男客户的信息,并且要求保证今后对该视图数据的修改都必须符合客户性别为男性这个条件。
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1849
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create or replace view mysql_test.customers_view
-> as
-> select * from mysql_test.customers where cust_sex='M'
-> with check option;
Query OK, 0 rows affected (0.03 sec)
mysql>
DROP VIEW [IF EXISTS]
view_name [,view_name] ...
[RESTRICT | CASCADE]
ALTERVIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
SHOW CREATE VIEW view_name
示例:
mysql> show create view customers_view;
+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View | Create View | character_set_client | collation_connection |
+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| customers_view | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `customers_view` AS select `customers`.`cust_id` AS `cust_id`,`customers`.`cust_name` AS `cust_name`,`customers`.`cust_sex` AS `cust_sex`,`customers`.`cust_city` AS `cust_city`,`customers`.`cust_address` AS `cust_address`,`customers`.`cust_contact` AS `cust_contact` from `customers` where (`customers`.`cust_sex` = 'M') WITH CASCADED CHECK OPTION | utf8mb4 | utf8mb4_0900_ai_ci |
+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
1 row in set (0.01 sec)
mysql>
由于视图是一个虚拟表,所以通过插入、修改和删除等操作方式来更新视图中的数据,实质上是在更新视图所引用的基本表中的数据。
只有满足可更新条件的视图才能进行更新,否则可能会导致系统出现不可预期的结果。
例子:在数据库 mysql_test 中,向视图 customers_view 插入一条记录:(909,'周明','M','武汉市','洪山区')。
mysql> insert into mysql_test.customers_view
-> values(909,'周明','M','武汉市','洪山区');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 武汉市 | NULL |
| 902 | 李四 | M | 武汉市 | NULL | NULL |
| 903 | 李四 | M | Beijing | 武汉市 | NULL |
| 904 | 李四 | M | Beijing | 武汉市 | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
4 rows in set (0.00 sec)
mysql> insert into mysql_test.customers_view values(909,'周明','M','武汉市','洪山区',null);
Query OK, 1 row affected (0.01 sec)
mysql>
例子:将视图 customer_view 中所有客户的 cust_address 列更新为“上海市”。
mysql> update mysql_test.customers_view set cust_address='上海市';
Query OK, 4 rows affected (0.01 sec)
Rows matched: 4 Changed: 4 Warnings: 0
mysql>
例子:删除视图 customers_view 中姓名为“周明”的客户信息。
mysql> delete from mysql_test.customers_view where cust_name='周明';
Query OK, 1 row affected (0.01 sec)
mysql>
注意:对于依赖多个基本表的视图,也是不能使用 DELETE 语句的。
视图用于查询检索,主要体现在这样一些应用:利用视图简化复杂的表连接;使用视图重新格式化检索出的数据;使用视图过滤不想要的数据。
例子:在视图 customers_view 中查找客户 id 号为905的客户姓名及其地址信息。
mysql> select cust_name,cust_address from mysql_test.customers_view where cust_id=905;
Empty set (0.00 sec)
mysql>
从SQL的入门基础到MySQL的实战应用,本文通过7大操作带你全面掌握数据库管理的核心技能。无论是定义数据库结构、管理数据更新,还是优化查询效率,SQL都展现了其简单却强大的魅力。通过理论与实践的结合,你不仅能理解数据库的运行逻辑,还能轻松应对实际开发场景。学完这篇,SQL不再是难题,而是你手中的利器——现在,就用这7大操作,开启你的数据库进阶之路吧!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!