网站底部有很多图标,网站建设长尾关键词,郑州市域名服务公司,网络营销推广怎么做比较好在此特别感谢尚硅谷-康师傅的MySQL精品教程 获取更好的阅读体验请前往我的博客主站! 如果本文对你的学习有帮助#xff0c;请多多点赞、评论、收藏#xff0c;你们的反馈是我更新最大的动力#xff01; 创建和管理表
1. 基础知识
1.1 一条数据存储的过程
存储数据是处理数… 在此特别感谢尚硅谷-康师傅的MySQL精品教程 获取更好的阅读体验请前往我的博客主站! 如果本文对你的学习有帮助请多多点赞、评论、收藏你们的反馈是我更新最大的动力 创建和管理表
1. 基础知识
1.1 一条数据存储的过程
存储数据是处理数据的第一步。只有正确地把数据存储起来我们才能进行有效的处理和分析。否则只能是一团乱麻无从下手。
那么怎样才能把用户各种经营相关的、纷繁复杂的数据有序、高效地存储起来呢 在 MySQL 中一个完整的数据存储过程总共有 4 步分别是创建数据库、确认字段、创建数据表、插入数据。 我们要先创建一个数据库而不是直接创建数据表呢
因为从系统架构的层次上看MySQL 数据库系统从大到小依次是数据库服务器、数据库、数据表、数据表的行与列。
MySQL 数据库服务器之前已经安装。所以我们就从创建数据库开始。
1.2 标识符命名规则
数据库名、表名不得超过30个字符变量名限制为29个必须只能包含 A–Z, a–z, 0–9, _共63个字符数据库名、表名、字段名等对象名中间不要包含空格同一个MySQL软件中数据库不能同名同一个库中表不能重名同一个表中字段不能重名必须保证你的字段没有和保留字、数据库系统或常用方法冲突。如果坚持使用请在SQL语句中使用着重号引起来保持字段名和类型的一致性在命名字段并为其指定数据类型的时候一定要保证一致性假如数据类型在一个表里是整数那在另一个表里可就别变成字符型了
1.3 MySQL中的数据类型
类型类型举例整数类型TINYINT、SMALLINT、MEDIUMINT、INT(或INTEGER)、BIGINT浮点类型FLOAT、DOUBLE定点数类型DECIMAL位类型BIT日期时间类型YEAR、TIME、DATE、DATETIME、TIMESTAMP文本字符串类型CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT枚举类型ENUM集合类型SET二进制字符串类型BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOBJSON类型JSON对象、JSON数组空间数据类型单值GEOMETRY、POINT、LINESTRING、POLYGON集合MULTIPOINT、MULTILINESTRING、MULTIPOLYGON、GEOMETRYCOLLECTION
其中常用的几类类型介绍如下
数据类型描述INT从-231到231-1的整型数据。存储大小为 4个字节CHAR(size)定长字符数据。若未指定默认为1个字符最大长度255VARCHAR(size)可变长字符数据根据字符串实际长度保存必须指定长度FLOAT(M,D)单精度占用4个字节M整数位小数位D小数位。 DM255,0D30默认MD6DOUBLE(M,D)双精度占用8个字节DM255,0D30默认MD15DECIMAL(M,D)高精度小数占用M2个字节DM650D30最大取值范围与DOUBLE相同。DATE日期型数据格式’YYYY-MM-DD’BLOB二进制形式的长文本数据最大可达4GTEXT长文本数据最大可达4G
2. 创建和管理数据库
2.1 创建数据库
方式1创建数据库
CREATE DATABASE 数据库名; 方式2创建数据库并指定字符集
CREATE DATABASE 数据库名 CHARACTER SET 字符集;方式3判断数据库是否已经存在不存在则创建数据库推荐
CREATE DATABASE IF NOT EXISTS 数据库名; 如果MySQL中已经存在相关的数据库则忽略创建语句不再创建数据库。 注意DATABASE 不能改名。一些可视化工具可以改名它是建新库把所有表复制到新库再删旧库完成的。 2.2 使用数据库
查看当前所有的数据库
SHOW DATABASES; #有一个S代表多个数据库查看当前正在使用的数据库
SELECT DATABASE(); #使用的一个 mysql 中的全局函数查看指定库下所有的表
SHOW TABLES FROM 数据库名;查看数据库的创建信息
SHOW CREATE DATABASE 数据库名;
或者
SHOW CREATE DATABASE 数据库名\G使用/切换数据库
USE 数据库名;注意要操作表格和数据之前必须先说明是对哪个数据库进行操作否则就要对所有对象加上“数据库名.”。 2.3 修改数据库
更改数据库字符集
ALTER DATABASE 数据库名 CHARACTER SET 字符集; #比如gbk、utf8等2.4 删除数据库
方式1删除指定的数据库
DROP DATABASE 数据库名;方式2删除指定的数据库推荐
DROP DATABASE IF EXISTS 数据库名;3. 创建表
3.1 创建方式1
必须具备 CREATE TABLE权限存储空间 语法格式
CREATE TABLE [IF NOT EXISTS] 表名(字段1, 数据类型 [约束条件] [默认值],字段2, 数据类型 [约束条件] [默认值],字段3, 数据类型 [约束条件] [默认值],……[表约束条件]
);加上了IF NOT EXISTS关键字则表示如果当前数据库中不存在要创建的数据表则创建数据表如果当前数据库中已经存在要创建的数据表则忽略建表语句不再创建数据表。 必须指定 表名列名(或字段名)数据类型长度 可选指定 约束条件默认值 创建表举例1
-- 创建表
CREATE TABLE emp (-- int类型emp_id INT,-- 最多保存20个中英文字符emp_name VARCHAR(20),-- 总位数不超过15位salary DOUBLE,-- 日期类型birthday DATE
);MySQL在执行建表语句时将id字段的类型设置为int(11)这里的11实际上是int类型指定的显示宽度默认的显示宽度为11。也可以在创建数据表的时候指定数据的显示宽度。
创建表举例2
CREATE TABLE dept(-- int类型自增deptno INT(2) AUTO_INCREMENT,dname VARCHAR(14),loc VARCHAR(13),-- 主键PRIMARY KEY (deptno)
);在MySQL 8.x版本中不再推荐为INT类型指定显示长度并在未来的版本中可能去掉这样的语法。 3.2 创建方式2 使用 AS subquery 选项将创建表和插入数据结合起来 指定的列和子查询中的列要一一对应 通过列名和默认值定义列
CREATE TABLE dept80
AS
SELECT employee_id, last_name, salary*12 ANNSAL, hire_date
FROM employees
WHERE department_id 80;
DESCRIBE dept80;3.3 查看数据表结构
在MySQL中创建好数据表之后可以查看数据表的结构。MySQL支持使用DESCRIBE/DESC语句查看数据表结构也支持使用SHOW CREATE TABLE语句查看数据表结构。
语法格式如下
SHOW CREATE TABLE 表名\G使用SHOW CREATE TABLE语句不仅可以查看表创建时的详细语句还可以查看存储引擎和字符编码。
4. 修改表
修改表指的是修改数据库中已经存在的数据表的结构。
使用 ALTER TABLE 语句可以实现 向已有的表中添加列 修改现有表中的列 删除现有表中的列 重命名现有表中的列
4.1 追加一个列
语法格式如下
ALTER TABLE 表名 ADD 【COLUMN】 字段名 字段类型 【FIRST|AFTER 字段名】;举例
ALTER TABLE dept80
ADD job_id varchar(15);4.2 修改一个列 可以修改列的数据类型长度、默认值和位置 修改字段数据类型、长度、默认值、位置的语法格式如下
ALTER TABLE 表名 MODIFY 【COLUMN】 字段名1 字段类型 【DEFAULT 默认值】【FIRST|AFTER 字段名2】;举例
ALTER TABLE dept80
MODIFY last_name VARCHAR(30);ALTER TABLE dept80
MODIFY salary double(9,2) default 1000;对默认值的修改只影响今后对表的修改此外还可以通过此种方式修改列的约束。这里暂先不讲。
4.3 重命名一个列
使用 CHANGE old_column new_column dataType子句重命名列。语法格式如下
ALTER TABLE 表名 CHANGE 【column】 列名 新列名 新数据类型;举例
ALTER TABLE dept80
CHANGE department_name dept_name varchar(15); 4.4 删除一个列
删除表中某个字段的语法格式如下
ALTER TABLE 表名 DROP 【COLUMN】字段名举例
ALTER TABLE dept80
DROP COLUMN job_id; 5. 重命名表
方式一使用RENAME
RENAME TABLE emp
TO myemp;方式二
ALTER table dept
RENAME [TO] detail_dept; -- [TO]可以省略必须是对象的拥有者
6. 删除表 在MySQL中当一张数据表没有与其他任何数据表形成关联关系时可以将当前数据表直接删除。 数据和结构都被删除 所有正在运行的相关事务被提交 所有相关索引被删除 语法格式
DROP TABLE [IF EXISTS] 数据表1 [, 数据表2, …, 数据表n];IF EXISTS的含义为如果当前数据库中存在相应的数据表则删除数据表如果当前数据库中不存在相应的数据表则忽略删除语句不再执行删除数据表的操作。
举例
DROP TABLE dept80;DROP TABLE 语句不能回滚
7. 清空表 TRUNCATE TABLE语句 删除表中所有的数据释放表的存储空间 举例
TRUNCATE TABLE detail_dept;TRUNCATE语句不能回滚而使用 DELETE 语句删除数据可以回滚 对比
SET autocommit FALSE;DELETE FROM emp2;
#TRUNCATE TABLE emp2;SELECT * FROM emp2;ROLLBACK;SELECT * FROM emp2;阿里开发规范 【参考】TRUNCATE TABLE 比 DELETE 速度快且使用的系统和事务日志资源少但 TRUNCATE 无事务且不触发 TRIGGER有可能造成事故故不建议在开发代码中使用此语句。 说明TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。 8. 内容拓展
拓展1阿里巴巴《Java开发手册》之MySQL字段命名 【强制】表名、字段名必须使用小写字母或数字禁止出现数字开头禁止两个下划线中间只出现数字。数据库字段名的修改代价很大因为无法进行预发布所以字段名称需要慎重考虑。 正例aliyun_adminrdc_configlevel3_name反例AliyunAdminrdcConfiglevel_3_name 【强制】禁用保留字如 desc、range、match、delayed 等请参考 MySQL 官方保留字。 【强制】表必备三字段id, gmt_create, gmt_modified。 说明其中 id 必为主键类型为BIGINT UNSIGNED、单表时自增、步长为 1。gmt_create, gmt_modified 的类型均为 DATETIME 类型前者现在时表示主动式创建后者过去分词表示被动式更新 【推荐】表的命名最好是遵循 “业务名称_表的作用”。 正例alipay_task 、 force_project、 trade_config 【推荐】库名与应用名称尽量一致。 【参考】合适的字符存储长度不但节约数据库表空间、节约索引存储更重要的是提升检索速度。 正例无符号值可以避免误存负数且扩大了表示范围。(例如那些永不为负的字段年龄……)
拓展2如何理解清空表、删除表等操作需谨慎
表删除操作将把表的定义和表中的数据一起删除并且MySQL在执行删除操作时不会有任何的确认信息提示因此执行删除操时应当慎重。在删除表前最好对表中的数据进行备份这样当操作失误时可以对数据进行恢复以免造成无法挽回的后果。
同样的在使用 ALTER TABLE 进行表的基本修改操作时在执行操作过程之前也应该确保对数据进行完整的备份因为数据库的改变是无法撤销的如果添加了一个不需要的字段可以将其删除相同的如果删除了一个需要的列该列下面的所有数据都将会丢失。
拓展3MySQL8新特性—DDL的原子化
在MySQL 8.0版本中InnoDB表的DDL支持事务完整性即DDL操作要么成功要么回滚。DDL操作回滚日志写入到data dictionary数据字典表mysql.innodb_ddl_log该表是隐藏的表通过show tables无法看到中用于回滚操作。通过设置参数可将DDL操作日志打印输出到MySQL错误日志中。
分别在MySQL 5.7版本和MySQL 8.0版本中创建数据库和数据表结果如下
CREATE DATABASE mytest;USE mytest;CREATE TABLE book1(
book_id INT ,
book_name VARCHAR(255)
);SHOW TABLES;1在MySQL 5.7版本中测试步骤如下 删除数据表book1和数据表book2结果如下
mysql DROP TABLE book1,book2;
ERROR 1051 (42S02): Unknown table mytest.book2再次查询数据库中的数据表名称结果如下
mysql SHOW TABLES;
Empty set (0.00 sec)从结果可以看出虽然删除操作时报错了但是仍然删除了数据表book1。
2在MySQL 8.0版本中测试步骤如下 删除数据表book1和数据表book2结果如下
mysql DROP TABLE book1,book2;
ERROR 1051 (42S02): Unknown table mytest.book2再次查询数据库中的数据表名称结果如下
mysql show tables;
------------------
| Tables_in_mytest |
------------------
| book1 |
------------------
1 row in set (0.00 sec)从结果可以看出数据表book1并没有被删除。
数据处理之增删改
1. 插入数据
解决方式使用 INSERT 语句向表中插入数据。
1.2 方式1VALUES的方式添加
使用这种语法一次只能向表中插入一条数据。
情况1为表的所有字段按默认顺序插入数据
INSERT INTO 表名
VALUES (value1,value2,....);值列表中需要为表的每一个字段指定值并且值的顺序必须和数据表中字段定义时的顺序相同。
举例
INSERT INTO departments
VALUES (70, Pub, 100, 1700);INSERT INTO departments
VALUES (100, Finance, NULL, NULL);情况2为表的指定字段插入数据
INSERT INTO 表名(column1 [, column2, …, columnn])
VALUES (value1 [,value2, …, valuen]);为表的指定字段插入数据就是在INSERT语句中只向部分字段中插入值而其他字段的值为表定义时的默认值。
在 INSERT 子句中随意列出列名但是一旦列出VALUES中要插入的value1,…valuen需要与column1,…columnn列一一对应。如果类型不同将无法插入并且MySQL会产生错误。
举例
INSERT INTO departments(department_id, department_name)
VALUES (80, IT);情况3同时插入多条记录
INSERT语句可以同时向数据表中插入多条记录插入时指定多个值列表每个值列表之间用逗号分隔开基本语法格式如下
INSERT INTO table_name
VALUES
(value1 [,value2, …, valuen]),
(value1 [,value2, …, valuen]),
……
(value1 [,value2, …, valuen]);或者
INSERT INTO table_name(column1 [, column2, …, columnn])
VALUES
(value1 [,value2, …, valuen]),
(value1 [,value2, …, valuen]),
……
(value1 [,value2, …, valuen]);举例
mysql INSERT INTO emp(emp_id,emp_name)- VALUES (1001,shkstart),- (1002,atguigu),- (1003,Tom);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0使用INSERT同时插入多条记录时MySQL会返回一些在执行单行插入时没有的额外信息这些信息的含义如下 ● Records表明插入的记录条数。 ● Duplicates表明插入时被忽略的记录原因可能是这些记录包含了重复的主键值。 ● Warnings表明有问题的数据值例如发生数据类型转换。 一个同时插入多行记录的INSERT语句等同于多个单行插入的INSERT语句但是多行的INSERT语句在处理过程中效率更高。因为MySQL执行单条INSERT语句插入多行数据比使用多条INSERT语句快所以在插入多条记录时最好选择使用单条INSERT语句的方式插入。 小结 VALUES也可以写成VALUE但是VALUES是标准写法。 字符和日期型数据应包含在单引号中。
1.3 方式2将查询结果插入到表中
INSERT还可以将SELECT语句查询的结果插入到表中此时不需要把每一条记录的值一个一个输入只需要使用一条INSERT语句和一条SELECT语句组成的组合语句即可快速地从一个或多个表中向一个表中插入多行。
基本语法格式如下
INSERT INTO 目标表名
(tar_column1 [, tar_column2, …, tar_columnn])
SELECT
(src_column1 [, src_column2, …, src_columnn])
FROM 源表名
[WHERE condition]在 INSERT 语句中加入子查询。不必书写 VALUES 子句。子查询中的值列表应与 INSERT 子句中的列名对应。
举例
INSERT INTO emp2
SELECT *
FROM employees
WHERE department_id 90;INSERT INTO sales_reps(id, name, salary, commission_pct)
SELECT employee_id, last_name, salary, commission_pct
FROM employees
WHERE job_id LIKE %REP%;2. 更新数据
使用 UPDATE 语句更新数据。语法如下
UPDATE table_name
SET column1value1, column2value2, … , columnvaluen
[WHERE condition]可以一次更新多条数据。 如果需要回滚数据需要保证在DML前进行设置SET AUTOCOMMIT FALSE; 使用 WHERE 子句指定需要更新的数据。
UPDATE employees
SET department_id 70
WHERE employee_id 113;如果省略 WHERE 子句则表中的所有数据都将被更新。
UPDATE copy_emp
SET department_id 110;更新中的数据完整性错误
UPDATE employees
SET department_id 55
WHERE department_id 110;说明不存在 55 号部门 3. 删除数据
使用 DELETE 语句从表中删除数据
DELETE FROM table_name [WHERE condition];table_name指定要执行删除操作的表“[WHERE ]”为可选参数指定删除条件如果没有WHERE子句DELETE语句将删除表中的所有记录。
使用 WHERE 子句删除指定的记录。
DELETE FROM departments
WHERE department_name Finance;如果省略 WHERE 子句则表中的全部数据将被删除
DELETE FROM copy_emp;删除中的数据完整性错误
DELETE FROM departments
WHERE department_id 60;说明You cannot delete a row that contains a primary key that is used as a foreign key in another table. 4. MySQL8新特性计算列
什么叫计算列呢简单来说就是某一列的值是通过别的列计算得来的。例如a列值为1、b列值为2c列不需要手动插入定义ab的结果为c的值那么c就是计算列是通过别的列计算得来的。
在MySQL 8.0中CREATE TABLE 和 ALTER TABLE 中都支持增加计算列。下面以CREATE TABLE为例进行讲解。
举例定义数据表tb1然后定义字段id、字段a、字段b和字段c其中字段c为计算列用于计算ab的值。 首先创建测试表tb1语句如下
CREATE TABLE tb1(
id INT,
a INT,
b INT,
c INT GENERATED ALWAYS AS (a b) VIRTUAL
);插入演示数据语句如下
INSERT INTO tb1(a,b) VALUES (100,200);查询数据表tb1中的数据结果如下
mysql SELECT * FROM tb1;
------------------------
| id | a | b | c |
------------------------
| NULL | 100 | 200 | 300 |
------------------------
1 row in set (0.00 sec)更新数据中的数据语句如下
mysql UPDATE tb1 SET a 500;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 05. 综合案例
# 1、创建数据库test01_library# 2、创建表 books表结构如下字段名字段说明数据类型id书编号INTname书名VARCHAR(50)authors作者VARCHAR(100)price价格FLOATpubdate出版日期YEARnote说明VARCHAR(100)num库存INT
# 3、向books表中插入记录# 1不指定字段名称插入第一条记录
# 2指定所有字段名称插入第二记录
# 3同时插入多条记录剩下的所有记录idnameauthorspricepubdatenotenum1Tal of AAADickes231995novel112EmmaTJane lura351993joke223Story of JaneJane Tim402001novel04Lovey DayGeorge Byron202005novel305Old landHonore Blade302010law06The BattleUpton Sara301999medicine407Rose HoodRichard haggard282008cartoon28
# 4、将小说类型(novel)的书的价格都增加5。# 5、将名称为EmmaT的书的价格改为40并将说明改为drama。# 6、删除库存为0的记录。# 7、统计书名中包含a字母的书# 8、统计书名中包含a字母的书的数量和库存总量# 9、找出“novel”类型的书按照价格降序排列# 10、查询图书信息按照库存量降序排列如果库存量相同的按照note升序排列# 11、按照note分类统计书的数量# 12、按照note分类统计书的库存量显示库存量超过30本的# 13、查询所有图书每页显示5本显示第二页# 14、按照note分类统计书的库存量显示库存量最多的# 15、查询书名达到10个字符的书不包括里面的空格# 16、查询书名和类型其中note值为novel显示小说law显示法律medicine显示医药cartoon显示卡通joke显示笑话# 17、查询书名、库存其中num值超过30本的显示滞销大于0并低于10的显示畅销为0的显示需要无货# 18、统计每一种note的库存量并合计总量# 19、统计每一种note的数量并合计总量# 20、统计库存量前三名的图书# 21、找出最早出版的一本书# 22、找出novel中价格最高的一本书# 23、找出书名中字数最多的一本书不含空格答案
#1、创建数据库test01_library
CREATE DATABASE IF NOT EXISTS test01_library CHARACTER SET utf8;#指定使用哪个数据库
USE test01_library;#2、创建表 books
CREATE TABLE books(id INT,name VARCHAR(50),authors VARCHAR(100) ,price FLOAT,pubdate YEAR ,note VARCHAR(100),num INT
);#3、向books表中插入记录
# 1不指定字段名称插入第一条记录
INSERT INTO books
VALUES(1,Tal of AAA,Dickes,23,1995,novel,11);
# 2指定所有字段名称插入第二记录
INSERT INTO books (id,name,authors,price,pubdate,note,num)
VALUES(2,EmmaT,Jane lura,35,1993,Joke,22);
# 3同时插入多条记录剩下的所有记录
INSERT INTO books (id,name,authors,price,pubdate,note,num) VALUES
(3,Story of Jane,Jane Tim,40,2001,novel,0),
(4,Lovey Day,George Byron,20,2005,novel,30),
(5,Old land,Honore Blade,30,2010,Law,0),
(6,The Battle,Upton Sara,30,1999,medicine,40),
(7,Rose Hood,Richard haggard,28,2008,cartoon,28);# 4、将小说类型(novel)的书的价格都增加5。
UPDATE books SET priceprice5 WHERE note novel;# 5、将名称为EmmaT的书的价格改为40并将说明改为drama。
UPDATE books SET price40,notedrama WHERE nameEmmaT;# 6、删除库存为0的记录。
DELETE FROM books WHERE num0;# 7、统计书名中包含a字母的书
SELECT * FROM books WHERE name LIKE %a%;# 8、统计书名中包含a字母的书的数量和库存总量
SELECT COUNT(*),SUM(num) FROM books WHERE name LIKE %a%;# 9、找出“novel”类型的书按照价格降序排列
SELECT * FROM books WHERE note novel ORDER BY price DESC;# 10、查询图书信息按照库存量降序排列如果库存量相同的按照note升序排列
SELECT * FROM books ORDER BY num DESC,note ASC;# 11、按照note分类统计书的数量
SELECT note,COUNT(*) FROM books GROUP BY note;# 12、按照note分类统计书的库存量显示库存量超过30本的
SELECT note,SUM(num) FROM books GROUP BY note HAVING SUM(num)30;# 13、查询所有图书每页显示5本显示第二页
SELECT * FROM books LIMIT 5,5;# 14、按照note分类统计书的库存量显示库存量最多的
SELECT note,SUM(num) sum_num FROM books GROUP BY note ORDER BY sum_num DESC LIMIT 0,1;# 15、查询书名达到10个字符的书不包括里面的空格
SELECT * FROM books WHERE CHAR_LENGTH(REPLACE(name, ,))10;/*
16、查询书名和类型其中note值为 novel显示小说law显示法律medicine显示医药cartoon显示卡通joke显示笑话
*/
SELECT name AS 书名 ,note, CASE note WHEN novel THEN 小说WHEN law THEN 法律WHEN medicine THEN 医药WHEN cartoon THEN 卡通WHEN joke THEN 笑话END AS 类型
FROM books;# 17、查询书名、库存其中num值超过30本的显示滞销大于0并低于10的显示畅销为0的显示需要无货
SELECT name,num,CASE WHEN num30 THEN 滞销WHEN num0 AND num10 THEN 畅销WHEN num0 THEN 无货ELSE 正常END AS 库存状态
FROM books;# 18、统计每一种note的库存量并合计总量
SELECT IFNULL(note,合计总库存量) AS note,SUM(num) FROM books GROUP BY note WITH ROLLUP;# 19、统计每一种note的数量并合计总量
SELECT IFNULL(note,合计总数) AS note,COUNT(*) FROM books GROUP BY note WITH ROLLUP;# 20、统计库存量前三名的图书
SELECT * FROM books ORDER BY num DESC LIMIT 0,3;# 21、找出最早出版的一本书
SELECT * FROM books ORDER BY pubdate ASC LIMIT 0,1;# 22、找出novel中价格最高的一本书
SELECT * FROM books WHERE note novel ORDER BY price DESC LIMIT 0,1;# 23、找出书名中字数最多的一本书不含空格
SELECT * FROM books ORDER BY CHAR_LENGTH(REPLACE(name, ,)) DESC LIMIT 0,1;