第一章:了解SQL
1.1数据库基础
数据库(database)保存有组织的数据的容器(通常是一个文件或一组文件)
人们通常用数据库这个术语来代表他们使用的数据库软件。这是不正确的,它是引起混淆的根源。确切地说,数据库软件应称为DBMS(数据库管理系统)。数据库是通过DBMS创建和操纵的容器。数据库可以是保存在硬设备上的文件,但也可以不是。在很大程度上说,数据库究竟是文件还是别的什么东西并不重要,因为你并不直接访问数据库;你使用的是DBMS,它替你访问数据库。
表(table)某种特定类型数据的结构化清单。
模式(schema)关于数据库和表的布局及特性的信息。也就是数据库及表的属性或者说是配置
列(column)表中的一个字段。所有表都是由一个或多个列组成的。
数据类型(datatype)所容许的数据的类型。每个表列都有相应的数据类型,它限制(或容许)该列中存储的数据。
行(row)表中的一个记录。
主键(primarykey)一列(或一组列),其值能够唯一区分表中每个行。
聚集函数(aggregate function) 运行在行组上,计算和返回单个值的函数。
1.2什么是SQL
SQL是结构化查询语言(StructuredQueryLanguage)的缩写。SQL是一种专门用来与数据库通信的语言。
优点:
- SQL不是某个特定数据库供应商专有的语言。几乎所有重要的DBMS都支持SQL,所以,学习此语言使你几乎能与所有数据库打交道
- SQL简单易学。它的语句全都是由描述性很强的英语单词组成,而且这些单词的数目不多。
- SQL尽管看上去很简单,但它实际上是一种强有力的语言,灵活使用其语言元素,可以进行非常复杂和高级的数据库操作。
DBMS专用的SQLSQL不是一种专利语言,而且存在一个标准委员会,他们试图定义可供所有DBMS使用的SQL语法,但事实上任意两个DBMS实现的SQL都不完全相同。本书讲授的SQL是专门针对MySQL的,虽然书中所讲授的多数语法也适用于其他DBMS,但不要认为这些SQL语法是完全可移植的。
第三章:使用MySQL
# 创建数据库
CREATE DATABASE 数据库名称;
# 选择数据库
USE 数据库名称;
# 显示数据库链表 后面有个s
SHOW DATABASES;
# 显示当前数据库中的表 后面有个s
SHOW TABLES;
# 显示一个表的字段
SHOW COLUMNS FROM 表名;
# MySQL支持用DESCRIBE作为SHOW COLUMNS FROM的一种快捷方式。🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
# 显示一个表的字段
DESCRIBE 表名; 等同于 SHOW COLUMNS FROM 表名;
第四章:检索数据SELECT
为了使用SELECT检索表数据,必须至少给出两条信息——想选择什么,以及从什么地方选择。
# 去重
SELECT DISTINCT 字段名 FROM 表名;
第五章:排序检索数据ORDERBY
# 对三个字段排序,且字段二 降序!
SELECT 字段1,字段2,字段3 FROM 表名 ORDER BY 字段1,字段2 DESC,字段3;
# 配合 LIMIT 找最大值和最小值
SELECT 字段 FROM 表名 ORDER BY 字段 LIMIT 1;
SELECT 字段 FROM 表名 ORDER BY 字段 DESC LIMIT 1;
第六章:过滤数据WHERE
MySQL在执行匹配时默认不区分大小写...WHEREprod_name='**f**uses';
可以匹配到Fuses
# 空值检查
SELECT 字段 FROM 表名 WHERE 字段 IS NULL;
SELECT 字段 FROM 表名 WHERE 字段 IS NOT NULL;
第十章:创建计算字段
10.1拼接字段Concat:
select concat(vend_name,'(',vend_country,')')
from vendors
order by vend_name;
+----------------------------------------+
| concat(vend_name,'(',vend_country,')') |
+----------------------------------------+
| ACME(USA) |
| Anvils R Us(USA) |
| Furball Inc.(USA) |
| Jet Set(England) |
| Jouets Et Ours(France) |
| LT Supplies(USA) |
+----------------------------------------+
10.2去空格trim()
select concat(rtrim(vend_name),'(',rtrim(vend_country),')')
from vendors
order by vend_name;
# rtrim()去掉右边所有空格
# ltrim()去掉左边所有空格
# trim()去掉两边
10.3使用别名AS
select concat(rtrim(vend_name),'(',rtrim(vend_country),')') as vend_title
from vendors
order by vend_name;
10.4执行算术计算
# 操作符: + - * /
select prod_id,quantity,item_price, quantity*item_price as expanded_price
from orderitems
where order_num=20005;
select 6*3;v
+-----+
| 6*3 |
+-----+
| 18 |
+-----+
select trim(' abd ');
+-----------------+
| trim(' abd ') |
+-----------------+
| abd |
+-----------------+
select now();
+---------------------+
| now() |
+---------------------+
| 2021-05-06 23:18:25 |
+---------------------+
第十一章:使用数据处理函数
11.1文本处理函数
# 大写upper()
select vend_name,upper(vend_name)
as vend_name_upcase
from vendors order by vend_name;
+----------------+------------------+
| vend_name | vend_name_upcase |
+----------------+------------------+
| ACME | ACME |
| Anvils R Us | ANVILS R US |
| Furball Inc. | FURBALL INC. |
| Jet Set | JET SET |
| Jouets Et Ours | JOUETS ET OURS |
| LT Supplies | LT SUPPLIES |
+----------------+------------------+
Left() 返回串左边的字符
Length() 返回串的长度
Locate() 找出串的一个子串
Lower() 将串转换为小写
LTrim() 去掉串左边的空格
Right() 返回串右边的字符
RTrim() 去掉串右边的空格
Soundex() 返回串的SOUNDEX值
SubString() 返回子串的字符
Upper() 将串转换为大写
11.2日期和时间处理函数
AddDate() 增加一个日期(天、周等)
AddTime() 增加一个时间(时、分等)
CurDate() 返回当前日期
CurTime() 返回当前时间
Date() 返回日期时间的日期部分 //👈👈👈
DateDiff() 计算两个日期之差
Date_Add() 高度灵活的日期运算函数
Date_Format() 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
DayOfWeek() 对于一个日期,返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
Now() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分
使用WHEREorder_date=’2005-09-01’可靠吗?order_date的数据类型为datetime。这种类型存储日期及时间值。样例表中的值全都具有时间值00:00:00,但实际中很可能并不总是这样。如果用当前日期和时间存储订单日期(因此你不仅知道订单日期,还知道下订单当天的时间),怎么办?比如,存储的order_date值为2005-09-0111:30:05,则WHEREorder_date=’2005-09-01’失败。即使给出具有该日期的一行,也不会把它检索出来,因为WHERE匹配失败。
解决办法是指示MySQL仅将给出的日期与列中的日期部分进行比较,而不是将给出的日期与整个列值进行比较。为此,必须使用Date()函数。Date(order_date)指示MySQL仅提取列的日期部分,更可靠的SELECT语句为:
select cust_id,order_num
from orders
where date(order_date) = '2005-09-01';
+---------+-----------+
| cust_id | order_num |
+---------+-----------+
| 10001 | 20005 |
+---------+-----------+
#范围查询
select cust_id,order_num
from orders
where date(order_date) between '2005-09-01' and '2005-09-30' ;
如果要的是日期,请使用Date()如果你想要的仅是日期,则使用Date()是一个良好的习惯,即使你知道相应的列只包含日期也是如此。这样,如果由于某种原因表中以后有日期和时间值,你的SQL代码也不用改变。当然,也存在一个Time()函数,在你只想要时间时应该使用它。Date()和Time()都是在MySQL4.1.1中第一次引入的。
11.3数值处理函数
Abs() 返回一个数的绝对值
Cos() 返回一个角度的余弦
Exp() 返回一个数的指数值
Mod() 返回除操作的余数
Pi() 返回圆周率
Rand() 返回一个随机数
Sin() 返回一个角度的正弦
Sqrt() 返回一个数的平方根
Tan() 返回一个角度的正切
第十二章:汇总数据
聚集函数(aggregate function) 运行在行组上,计算和返回单个值的函数。
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和
12.1、AVG()函数
select avg(prod_price) as avg_price
from products
where vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 13.212857 |
+-----------+
# 🔥AVG()函数忽略列值未NULL的行🔥
12.2、COUNT()函数
select count(*) as num_cust
from customers;
+----------+
| num_cust |
+----------+
| 5 |
+----------+
select count(cust_email) as num_cust
from customers;
+----------+
| num_cust |
+----------+
| 3 |
+----------+
# 🔥如果指定列名,则指定列的值为空的行被COUNT()函数忽略,但如果COUNT()函数中用的是星号(*),则不忽略🔥
12.3、MAX()函数
select prod_name,max(prod_price) as max_price
from products;
+--------------+-----------+
| prod_name | max_price |
+--------------+-----------+
| .5 ton anvil | 55.00 |
+--------------+-----------+
# 🔥MAX()函数忽略列值为NULL的行。🔥
对非数值数据使用MAX() :
虽然MAX()一般用来找出最大的数值或日期值,但MySQL允许将它用来返回任意列中的最大值,包括返回文本列中的最大值。在用于文本数据时,如果数据按相应的列排序,则MAX()返回最后一行。
12.4、MIN()函数
select prod_name,min(prod_price) as max_price
from products;
+--------------+-----------+
| prod_name | max_price |
+--------------+-----------+
| .5 ton anvil | 2.50 |
+--------------+-----------+
# 🔥MIN()函数忽略列值为NULL的行。🔥
对非数值数据使用MIN() :
MIN()函数与MAX()函数类似,MySQL允许将它用来返回任意列中的最小值,包括返回文本列中的最小值。在用于文本数据时,如果数据按相应的列排序,则MIN()返回最前面的行。
12.5、SUM()函数
select sum(item_price*quantity) as total_price
from orderitems
where order_num = 20005;
+-------------+
| total_price |
+-------------+
| 149.87 |
+-------------+
# 🔥SUM()函数忽略列值为NULL的行。🔥
在多个列上进行计算:
如本例所示,利用标准的算术操作符,所有聚集函数都可用来执行多个列上的计算。
12.6、聚集不同值DISTINCT
select avg(distinct prod_price) as avg_price from products where vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 15.998000 |
+-----------+
select avg(prod_price) as avg_price from products where vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 13.212857 |
+-----------+
select distinct(vend_id) as avg_price
from products;
+-----------+
| avg_price |
+-----------+
| 1001 | | 1002 | | 1003 | | 1005 |
+-----------+
如果指定列名,则DISTINCT只能用于COUNT()。DISTINCT不能用于COUNT(),因此不允许使用COUNT(DISTINCT),否则会产生错误。类似地,*DISTINCT必须使用列名,不能用于计算或表达式。
12.7、组合聚集函数
select count(*) as num_items,
min(prod_price) as min_price,
max(prod_price) as max_price,
avg(prod_price) as avg_price
from products;
+-----------+-----------+-----------+-----------+
| num_items | min_price | max_price | avg_price |
+-----------+-----------+-----------+-----------+
| 14 | 2.50 | 55.00 | 16.133571 |
+-----------+-----------+-----------+-----------+
小结
聚集函数用来汇总数据。MySQL支持一系列聚集函数,可以用多种方法使用它们以返回所需的结果。这些函数是高效设计的,它们返回结果一般比你在自己的客户机应用程序中计算要快得多。
第二十三章:使用存储过程
创建存储过程
DELIMITER // 👈表示命令行实用程序使用//作为新的语句分隔符,👇下面END后面结束,最后恢复原来的分号分隔符
👇👇👇-- 表示注释
-- Name: ordertotal
-- Parameters: onumber = order number
-- taxable = 0 if not taxable,1 if taxable
-- ototal = order total variable
CREATE PROCEDURE ordertotal( 👈创建存储过程 括号内填入参数
IN onumber INT, 👈 IN 表示入参 后面跟类型
IN taxable BOOLEAN, 👈 IN 表示入参 后面跟类型
OUT ototal DECIMAL(8,2) 👈 IN 表示返回值 后面跟类型
)COMMENT 'Obtain order total , optionally adding tax' 👈 COMMENT 表示描述即存储过程注释
BEGIN 👈存储过程体开始
-- Declare variable for total
DECLARE total DECIMAL(8,2); 👈 DECLARE 创建变量 后面跟变量名 及 数据类型
-- Declare tax percentage
DECLARE taxrate INT DEFAULT 6; 👈 DECLARE 创建变量 后面跟变量名 及 数据类型
-- Get the order total
SELECT SUM(item_price*quantity)
FROM orderitems
WHERE order_num = onumber
INTO total; 👈 将结果输出(保存)到total中
-- Is this taxable?
IF taxable THEN 👈 IF 判断 0为false 1(非0数字)为true
-- Yes, so add taxrate to the total
SELECT total+(total/100*taxrate) INTO total;
END IF;
-- And finally, save to out variable
SELECT total INTO ototal; 👈 将total保存的数据保存到我们的参数ototal中,这样我们就可以取到结果
END // 👈存储过程体结束
DELIMITER; 👈下面END后面结束,最后恢复原来的分号分隔符
调用存储过程
# 第一步
CALL ordertotal(20005,0,@total); 👈 CALL 调用存储过程
# CALL调用并不会返回数据需要我们查询
# 第二步
SELECT @total; 👈 查询调用后的结果