Mysql:
apt-get install mysql-client-5.7
apt-get install mysql-server-5.7
5.检查mysql是否启动
1.查看mysql进程是否运行
ps -ef | grep mysql
2.查看msyql 监听端口
netstat -tap | grep mysql
6. msyql服务停止
service mysql stop
如果不是root用户请执行
sudo service mysql stop
7. Mysql 服务启动
service mysql start
8. Mysql 服务重启
service mysql restart
当运行mysql时出现下面的问题:(当前用户没有权限)
ERROR 1045 (28000): Access denied for user ‘zhengyi’@’localhost’ (using password: NO)
解决方法:
使用账号+密码的方式登入
mysql -u root -p
创建新用户:
CREATE USER ‘zheng’@’localhost’ IDENTIFIED BY ‘12345’;
SHOW DATABASES; 返回可用数据库的列表
SHOW TABLES; 获取数据库表内的表的列表
SHOW COLUMNS FROM customers;
CREATE DATABASES mydb; 创建数据库
-> USE mydb;
-> CREATE TABLE orders 创建数据表
-> (
-> order_num int NOT NULL AUTO_INCREMENT,
-> order_data datetime NOT NULL,
-> cust_id int NOT NULL,
-> PRIMARY KEY (order_num)
-> )ENGINE=InnoDB;
-> DESCRIBE orders 显示表结构
C API:
数据库名: crashcourse.
表名: products
第四章、检索数据
4.1 SELECT 语句
返回的语句是没有排序的
4.2 检索单个列
SELECT prod_name
FROM products;
4.3 检索多个列
SELECT prod_id,prod_name,prod_price
FROM products;
4.4 检索所有列
SELECT * FROM products;
4.5 检索不同的行 DISTINCT-去除重复
SELECT DISTINCT vend_id
FROM products;
4.6 限制结果 LIMIT
SELECT prod_name
FROM products
LIMIT 5;
返回不多于5行
SELECT prod_name
FROM products
LIMIT 5,5;
返回从第5行开始的5行
行0:检测出来的第一行为0不为1
4.7使用完全限定的表名
SELECT products.prod_name
FROM crashcourse.products;
第五章:排序检索数据
ORDER BY 默认增序
DESC 降序
ASC 升序
5.1 排序数据
SELECT prod_name
FROM products
ORDER BY prod_name;
5.2 按多个列排序
SELECT prod_id,prod_name,prod_price
FROM products
ORDER BY prod_price,prod_name;
5.3 指定方向排序
SELECT prod_id,prod_name,prod_price
FROM products
ORDER BY prod_price DESC;
SELECT prod_id,prod_name,prod_price
FROM products
ORDER BY prod_price DESC,prod_name;
最贵的在前面,然后对产品排序
SELECT prod_price
FROM products
ORDER BY prod_price DESC
LIMIT 1
找到最贵的物品
第六章 过滤数据
6.1 使用WHERE 子句
只检索指定条件
SELECT prod_name,prod_price
FROM products
WHERE prod_price = 2.50;
检索两个列 只返回prod_price =2.5的行
在同时使用 ORDER BY 和 WHERE 子句时,应
该让 ORDER BY 位于 WHERE 之后, 否则将会产生错误
6.2 WHERE 操作符
= <> != < <= > >= BETWEEN
6.2.1 检查单个值
SELECT prod_name,prod_price
FROM products
WHERE prod_name = ‘fuses’;
默认不区分字符大小写
SELECT prod_name,prod_price
FROM products
WHERE prod_price < 10 ;
6.2.2 不匹配检查
SELECT vend_id,prod_name
FROM products
WHERE vend_id != 1003;
返回不是1003的
6.2.3 范围值检查 BETWEEN
SELECT prod_name,prod_price
FROM products
WHERE prod_price BETWEEN 5 AND 10;
返回5~10之间的包括两端
6.2.4 空值检查 NULL 无值
SELECT prod_name
FROM products
WHERE prod_price IS NULL;
检索价格为空值(不是0值)
第七章 数据过滤
7.1 组合 WHERE 子句
7.1.1 AND 操作符
多个 过滤条件
SELECT prod_id,prod_name,prod_price
FROM products
WHERE vend_id = 1003 AND prod_price <= 10;
还可以添加多个过滤条件,每添加一条就要使用一个AND。
7.1.2 OR 操作符
匹配任意条件的行
SELECT prod_name,prod_price
FROM products
WHERE vend_id =1002 OR vend_id =1003;
7.1.3 计算优先级次序
SELECT prod_name,prod_price
FROM products
WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
7.2 IN 操作符
IN用来指定条件范围,范围中的每个条件都可以进行匹配
SELECT prod_name,prod_price
FROM products
WHERE vend_id IN(1002,1003)
ORDER BY prod_name;
1002 和 1003 的所有产品
等价 WHERE vend_id = 1002 OR vend_id = 1003
IN的有点:
在使用长的合法选项清单时, IN操作符的语法更清楚且更直观
在使用 IN 时,计算的次序更容易管理(因为使用的操作符更少)
IN 操作符一般比OR操作符清单执行更快
IN 的最大优点是可以包含其他SELECT语句,使得能够更动态地建
立WHERE子句。第14章将对此进行详细介绍
7.3 NOT 操作符
否定它之后跟的任何条件
SELECT prod_name,prod_price
FROM products
WHERE vend_id NOT IN(1002,1003)
ORDER BY prod_name;
列出 除 1002 1003之外的产品
NOT 支持对 IN、BETWEEN、EXISTS 子句 取反
第八章 用通配符进行过滤
8.1 LIKE 操作符
8.1.1 百分号 % 通配符
% 表示 任何字符出现任意次数
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE ‘s%e’
找出以 s开头 e结尾的产品
不能用%来匹配NULL值
8.1.2 下划线_通配符
只匹配单个字符
SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE ‘s_e’
_总是匹配一个字符,不能多也不能少
8.2 使用通配符的技巧
不要过度使用通配符,如果其他操作符能达到相同的目的,应该使用其他操作符
在确实需要使用通配符时,除非绝对有必要,否则不要把他们用在
搜索模式的开始处,是最慢的
仔细注意通配符的位置
第九章 正则表达式进行搜索
9.1 LIKE 匹配整个串 REGEXP 匹配整个子串
9.2.1 基本字符匹配
SELECT prod_name
FROM products
WHERE prod_name REGEXP ‘1000’
ORDER BY prod_name;
LIKE 被 REGEXP替换,匹配name中含有1000的进行匹配
LIKE匹配的是正行,REGEXP匹配的是整个行中一部分值
匹配大小写:可使用 BINARY 关键字
WHERE prod_name REGEXP BINARY ‘Jet Pack .000’
9.2.2 OR 匹配
为搜索两个串之一(或者这一个或者另外一个)使用|,
SELECT prod_name
FROM products
WHERE prod_name REGEXP ‘1000|2000’
ORDER BY prod_name;
返回1000 和2000 都 匹配的
两个以上的OR条件,
‘1000|2000|3000’ 将匹配1000 或 2000 或 3000
9.2.3 匹配几个字符之一
SELECT prod_name
FROM products
WHERE prod_name REGEXP ‘[123] ton’
ORDER BY prod_name;
使用了正则表达式[123] Ton。 [123]定义一组字符,它
的意思是匹配1或2或3,因此, 1 ton和2 ton都匹配且返回(没
有3 ton)。
[]是另一种形式的OR语句。 事实上,正则表达式[123]Ton
为[1|2|3]Ton的缩写
但[^123]却匹配除这些字符外的任何东西
9.2.4 匹配范围
集合可以用来定义匹配的一个或多个字符
[0123456789]匹配0到9,等价[0-9]
[1-3]和[6-9]也是合法的范围。
[a-z]匹配任意字母字符
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[1-5] ton'
ORDER BY prod_name;
9.2.5 匹配特殊字符 \转义字符
为了匹配特殊字符,必须用\为前导。
\-表示查找-, \.表示查找. ,\\ 表示查找\。
9.2.6 匹配字符类
[:alnum:] 任意字母和数字(同[a-zA-Z0-9])
[:alpha:] 任意字符(同[a-zA-Z])
[:blank:] 空格和制表(同[\t])
[:cntrl:] ASCII控制字符( ASCII 0到31和127)
[:digit:] 任意数字(同[0-9])
[:graph:] 与[:print:]相同,但不包括空格
[:lower:] 任意小写字母(同[a-z])
[:print:] 任意可打印字符
[:punct:] 既不在[:alnum:]又不在[:cntrl:]中的任意字符
[:space:] 包括空格在内的任意空白字符(同[\f\n\r\t\v])
[:upper:] 任意大写字母(同[A-Z])
[:xdigit:] 任意十六进制数字(同[a-fA-F0-9])
9.2.7 匹配多个实例
重复元字符
* 0个或多个匹配
+ 1个或多个匹配(等于{1,})
? 0个或1个匹配(等于{0,1})
{n} 指定数目的匹配
{n,} 不少于指定数目的匹配
{n,m} 匹配数目的范围( m不超过255)
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[[:digit:]]{4}'
ORDER BY prod_name;
[:digit:]匹配任意数字,因而它为数字的一个集合。
{4}确切地要求它前面的字符(任意数字)出现4次,
所以[[:digit:]]{4}匹配连在一起的任意4位数字。
9.2.8 定位符
定位元字符
^ 文本的开始
$ 文本的结尾
[[:<:]] 词的开始
[[:>:]] 词的结尾
SELECT prod_name
FROM products
WHERE prod_name REGEXP '^[0-9\\.]'
ORDER BY prod_name;
^匹配串的开始。因此, ^[0-9\\.]只在.或任意数字为串中第
一个字符时才匹配它们。没有^, 则还要多检索 (那些中间有数字的行)
第十章 创建计算字段
MySQL除了支持RTrim()(正如刚才所见,它去掉
串右边的空格),还支持LTrim()(去掉串左边的空格)以及
Trim()(去掉串左右两边的空格)。
10.1 计算字段
vendors表包含供应商名和位置信息。
表中数据存储在两个列vend_name和vend_
country中。此外,需要用括号将vend_country括起来,
10.2 拼接字段
拼接( concatenate) 将值联结到一起构成单个值。
SELECT Concat(vend_name,'(',vend_country,')')
FROM vendors
ORDER BY vend_name;
Concat()拼接串,即把多个串连接起来形成一个较长的串。
Concat()需要一个或多个指定的串,各个串之间用逗号分隔。
SELECT Concat(RTrim(vend_name),'(',RTrim(vend_country),')') AS
vend_title
FROM vendors
ORDER BY vend_name;
别名( alias) 是一个字段或值
的替换名。别名用AS关键字赋予
10.3 执行算术计算
orders表包含收到的所有订单, orderitems表包含每个订单中的
各项物品。下面的SQL语句检索订单号20005中的所有物品:
item_price列包含订单中每项物品的单价。如下汇总物品的价格(单
价乘以订购数量):
输出中显示的expanded_price列为一个计算字段,此计算为
quantity*item_price。客户机应用现在可以使用这个新计算
列,就像使用其他列一样。
SELECT prod_id,quantity,item_price,
quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num = 20005
10.4 MySQL算术操作符
+ 加
- 减
* 乘
/ 除
第十一章 使用数据处理函数
11.1 函数
11.2.1 文本处理函数
Left() 返回串左边的字符
Length() 返回串的长度
Locate() 找出串的一个子串
Lower() 将串转换为小写
LTrim() 去掉串左边的空格
Right() 返回串右边的字符
RTrim() 去掉串右边的空格
Soundex() 返回串的SOUNDEX值
SubString() 返回子串的字符
Upper() 将串转换为大写
11.2.2 日期和时间处理函数
常用日期和时间处理函数
AddDate() 增加一个日期(天、周等)
AddTime() 增加一个时间(时、分等)
CurDate() 返回当前日期
CurTime() 返回当前时间
Date() 返回日期时间的日期部分
DateDiff() 计算两个日期之差
Date_Add() 高度灵活的日期运算函数
Date_Format() 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
DayOfWeek() 对于一个日期,返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
Now() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分
11.2.3 数值处理函数
Abs() 返回一个数的绝对值
Cos() 返回一个角度的余弦
Exp() 返回一个数的指数值
Mod() 返回除操作的余数
Pi() 返回圆周率
Rand() 返回一个随机数
Sin() 返回一个角度的正弦
Sqrt() 返回一个数的平方根
Tan() 返回一个角度的正切
第12章 汇总数据
12.1 聚集函数
确定表中行数
获得表中行组的和
找出表列(或所有行或某些特定的行)的最大值、最小值和平均值
SQL聚集函数
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和
使用AVG()返回products表中所有产品的平均价格:
SELECT AVG(prod_price) AS avg_price
FROM products;
子返回特定供
应商所提供产品的平均价格
SELECT AVG(prod_price) AS avg_price
FROM products;
WHERE vend_id = 1003;
AVG()只能用来确定特定数值列的平均值,而
且列名必须作为函数参数给出。为了获得多个列的平均值,
必须使用多个AVG()函数。
NULL值 AVG()函数忽略列值为NULL的行
12.1.2 COUNT()函数
使用COUNT(*)对表中行的数目进行计数, 不管表列中包含的是空值( NULL)还是非空值。
使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。
返回customers表中客户的总数:
SELECT COUNT(*) AS num_cust
FROM customers;
利用COUNT(*)对所有行计数,不管行中各列有什么值。
计数值在num_cust中返回
只对具有电子邮件地址的客户计数:
SELECT COUNT(cust_eamil) AS num_cust
FROM customers;
这条SELECT语句使用COUNT(cust_email)对cust_email列中有值的行进行计数。
NULL值 如果指定列名,则指定列的值为空的行被COUNT()函数忽略,
但如果COUNT()函数中用的是星号( *),则不忽略。
12.1.3 MAX()函数
MAX()返回指定列中的最大值。 MAX()要求指定列名
SELECT MAX(prod_price) AS max_price
FROM products;
对非数值数据使用MAX() 虽然MAX()一般用来找出最大的
数值或日期值,但MySQL允许将它用来返回任意列中的最大
值,包括返回文本列中的最大值。在用于文本数据时,如果数
据按相应的列排序,则MAX()返回最后一行。
NULL值 MAX()函数忽略列值为NULL的行。
12.1.4 MIN()函数
它返回指定列的最小值
SELECT MIN(prod_price) AS min_price
FROM products;
NULL值 MIN()函数忽略列值为NULL的行
12.1.5 SUM()函数
SUM()用来返回指定列值的和(总计)。
orderitems表包含订单中实际的物品,每个物品有相应的数量( quantity)。
可如下检索所订购物品的总数(所有quantity值之和):
SELECT SUM(quantity) AS item_ordered
FROM orderitems
WHERE order_num = 20005;
函数SUM(quantity)返回订单中所有物品数量之和,
WHERE子句保证只统计某个物品订单中的物品。
合计每项物品的item_price*quantity,得出总的订单金额
SELECT SUM(item_price*quantity) AS total_price
FROM orderitems
WHERE order_num = 20005;
函数SUM(item_price*quantity)返回订单中所有物品价钱之和,
WHERE子句同样保证只统计某个物品订单中的物品
在多个列上进行计算 如本例所示,利用标准的算术操作符,
所有聚集函数都可用来执行多个列上的计算
NULL值 SUM()函数忽略列值为NULL的行。
12.2 聚集不同值
对所有的行执行计算,指定ALL参数或不给参数(因为ALL是默认
行为);
只包含不同的值,指定DISTINCT参数
下面的例子使用AVG()函数返回特定供应商提供的产品的平均价格。
它与上面的SELECT语句相同,但使用了DISTINCT参数,因此平均值只
考虑各个不同的价格:
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM products
WHERE vend_id = 1003;
如果指定列名,则DISTINCT只能用于COUNT()。DISTINCT
不能用于COUNT(*),因此不允许使用COUNT( DISTINCT),
否则会产生错误。类似地, DISTINCT必须使用列名,不能用
于计算或表达式
将DISTINCT用于MIN()和MAX() 虽然DISTINCT从技术上可
用于MIN()和MAX(),但这样做实际上没有价值。一个列中的
最小值和最大值不管是否包含不同值都是相同的
12.3 组合聚集函数
SELECT 语句可根据需要包含多个聚集函数
SELECT COUNT(*) AS num_items,
MIN(prod_price) AS price_min,
MAX(prod_price) AS price_max,
AVG(prod_price) AS price_avg
FROM products;
这里用单条SELECT语句执行了4个聚集计算,返回4个值
( products表中物品的数目,产品价格的最高、最低以及平均
值)
取别名 在指定别名以包含某个聚集函数的结果时,不应该使
用表中实际的列名。虽然这样做并非不合法,但使用唯一的名
字会使你的SQL更易于理解和使用 (以及将来容易排除故障)
第13章 分组数据
涉及两个新SELECT语句子句,
分别是GROUP BY子句和HAVING子句
13.1 数据分组
分组允许把数据分为多个逻辑组,以
便能对每个组进行聚集计算。
13.2 创建分组
分组是在SELECT语句的GROUP BY子句中建立的
SELECT vend_id,COUNT(*) AS num_prods
FROM products
GROUP BY vend_id;
指定了两个列, vend_id包含产品供应商的ID,
num_prods为计算字段(用COUNT(*)函数建立)。
GROUP BY子句指示MySQL按vend_id排序并分组数据。
这导致对每个vend_id而不是整个表计算num_prods一次。
从输出中可以看到,
供应商1001有3个产品,
供应商1002有2个产品,
供应商1003有7个产品,
而供应商1005有2个产品
GROUP BY 重要的规定
1、GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套,
为数据分组提供更细致的控制。
2、如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上
进行汇总。换句话说,在建立分组时,指定的所有列都一起计算
(所以不能从个别的列取回数据)
3、GROUP BY子句中列出的每个列都必须是检索列或有效的表达式
(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在
GROUP BY子句中指定相同的表达式。不能使用别名。
4、除聚集计算语句外, SELECT语句中的每个列都必须在GROUP BY子
句中给出。
5、如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列
中有多行NULL值,它们将分为一组。
6、GROUP BY子句必须出现在WHERE子句之后, ORDER BY子句之前
使用 ROLLUP 使用 WITH ROLLUP 关键字,可以得到每个分组以
及每个分组汇总级别(针对每个分组)的值,如下所示:
SELECT vend_id,COUNT(*) AS num_prods
FROM products
GROUP BY vend id WITH ROLLUP;
13.3 过滤分组
规定包括哪些分组,排除哪些分组
唯一的差别是WHERE过滤行,而HAVING过滤分组。
SELECT cust_id,COUNT(*) AS orders
FROM orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;
过滤COUNT(*) >=2(两个以上的订单)的那些分组。
HAVING和WHERE的差别 :
WHERE在数据分组前进行过滤, HAVING在数据分组后进行过滤。
列出具有2个(含)以上、价格为10(含)以上的产品的供应商:
SELECT vend_id,COUNT(*) AS num_prods
FROM products
WHERE prod_price >= 10
GROUP BY vend_id
HAVING COUNT(*) >= 2;
13.4 分组和排序
分组不一定有序
SELECT order_num,SUM(quantity*item_price) >= 50
FROM orderitems
GROUP BY order_num
HAVING SUM(quantity*item_price) >= 50
ORDER BY ordertotal;
GROUP BY子句用来按订单号( order_num列)
分组数据,以便SUM(*)函数能够返回总计订单价格。 HAVING子
句过滤数据,使得只返回总计订单价格大于等于50的订单。最后, 用ORDER
BY子句排序输出。
13.5 SELECT子句顺序
SELECT子句及其顺序
子句 说明 是否必须使用
SELECT 要返回的列或表达式 是
FROM 从中检索数据的表 仅在从表选择数据时使用
WHERE 行级过滤 否
GROUP BY 分组说明 仅在按组计算聚集时使用
HAVING 组级过滤 否
ORDER BY 输出排序顺序 否
LIMIT 要检索的行数 否
第14章 使用子查询
14.1 子查询
迄今为止我们所看到的所有SELECT语句
都是简单查询,即从单个数据库表中检索数据的单条语句。
SQL还允许创建子查询( subquery) ,即嵌套在其他查询中的查询。
14.2 利用子查询进行过滤
订单存储在两个表中。对于包含订单号、客户ID、订单日期的每个订单,
orders表存储一行。各订单的物品存储在相关的orderitems表中。
orders表不存储客户信息。它只存储客户的ID。
实际的客户信息存储在customers表中
假如需要列出订购物品TNT2的所有客户,应该怎样检索?下面列出具体的步骤。
(1) 检索包含物品TNT2的所有订单的编号。
(2) 检索具有前一步骤列出的订单编号的所有客户的ID。
(3) 检索前一步骤返回的所有客户ID的客户信息。
上述每个步骤都可以单独作为一个查询来执行。可以把一条SELECT
语句返回的结果用于另一条SELECT语句的WHERE子句。
也可以使用子查询来把3个查询组合成一条语句。
第一条SELECT语句的含义很明确,对于prod_id为TNT2的所有订单物
品,它检索其order_num列。输出列出两个包含此物品的订单:
SELECT order_num
FROM orderitems
WHERE prod_id = ‘TNT2’
下一步,查询具有订单20005和20007的客户ID。利用第7章介绍的IN
子句,编写如下的SELECT语句:
SELECT cust_id
FROM orders
WHERE order_num IN(20005,20007);
现在,把第一个查询(返回订单号的那一个)变为子查询组合两个
查询。请看下面的SELECT语句
SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id = ‘TNT2’);
在SELECT语句中,子查询总是从内向外处理。在处理上面的
SELECT语句时, MySQL实际上执行了两个操作。
现在得到了订购物品TNT2的所有客户的ID。下一步是检索这些客户
ID的客户信息。检索两列的SQL语句为:
SELECT cust_name,cust_contact
FROM customers
WHERE cust_id IN (10001,10004);
可以把其中的WHERE子句转换为子查询而不是硬编码这些客户ID:
SELECT cust_name,cust_contact
FROM customers
WHERE cust_id IN (SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id = ‘TNT2’));
第十五章 联结表
15.1 联结(join)
15.1.1 关系表
建立两个表,一个存储供应商信息,另一个存储产品信息。
vendors表包含所有供应商信息,每个供应商占一行,每个供
应商具有唯一的标识。此标识称为主键( primary key)
products表只存储产品信息,它除了存储供应商ID( vendors表的主
键)外不存储其他供应商信息。vendors表的主键又叫作products的外键,
它将vendors表与products表关联,利用供应商ID能从vendors表中找出
相应供应商的详细信息。
外键( foreign key) 外键为某个表中的一列,它包含另一个表
的主键值,定义了两个表之间的关系。
15.1.2 为什么要使用联结
分解数据为多个表能更有效地存储,更方便地处理,并
且具有更大的可伸缩性。但这些好处是有代价的
如果数据存储在多个表中,怎样用单条SELECT语句检索出数据?
答案是使用联结。简单地说,联结是一种机制,用来在一条SELECT
语句中关联表,因此称之为联结。使用特殊的语法,可以联结多个表返
回一组输出,联结在运行时关联表中正确的行。
15.2 创建联结
规定要联结的所有表以及它们如何关联即可。
请看下面的例子
SELECT vend_name,prod_name,prod_price
FROM vendors,products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name,prod_name;
这条语句的FROM子句列出了两个表,分别是vendors和products。
它们就是这条SELECT语句联结的两个表的名字。
这两个表用WHERE子句正确联结
WHERE子句指示MySQL匹配vendors表中的vend_id和products表中的vend_id
完全限定列名 在引用的列可能出现二义性时,必须使用完
全限定列名(用一个点分隔的表名和列名)。如果引用一个
没有用表名限制的具有二义性的列名, MySQL将返回错误
15.2.1 WHERE子句的重要性
笛卡儿积( cartesian product)
由没有联结条件的表关系返回的结果为笛卡儿积。
检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
15.2.2 内部联结
目前为止所用的联结称为等值联结( equijoin),它基于两个表之间的
相等测试。这种联结也称为内部联结。其实,对于这种联结可以使用稍
微不同的语法来明确指定联结的类型。下面的SELECT语句返回与前面例
子完全相同的数据:
SELECT vend_name,prod_name,prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
两个表之间的关系是FROM子句的组成部分,以INNER
JOIN指定。在使用这种语法时,联结条件用特定的ON子句而不是WHERE
子句给出。传递给ON的实际条件与传递给WHERE的相同
15.2.3 联结多个表
SQL对一条SELECT语句中可以联结的表的数目没有限制。创建联结
的基本规则也相同。首先列出所有表,然后定义表之间的关系。
SELECT prod_name,vend_name,prod_price,quantity
FROM orderitems,products,vendors
WHERE products.vend_id = vendors.vend_id
AND orderitems.prod_id = products.prod_id
AND order_num = 20005;
此例子显示编号为20005的订单中的物品
这里的FROM子句列出了3个表,而WHERE子句定义了这两个联结条件,
而第三个联结条件用来过滤出订单20005中的物品。
正如第14章所述,子查询并不总是执行复杂SELECT操作的最有效的
方法,下面是使用联结的相同查询:
SELECT cust_name,cust_contact
FROM customers,orders,orderitems
WHERE customers.cust_id = orders.cust_id
AND orderitems.order_num = orders.order_num
AND prod_id = ‘TNT2’;
这个查询中返回数据需要使用3个表。
使用了两个联结。这里有3个WHERE子句条件。
前两个关联联结中的表,后一个过滤产品TNT2的数据
第十七章 组合查询
有两种基本情况,其中需要使用组合查询:
在单个查询中从不同的表返回类似结构的数据;
对单个表执行多个查询,按单个查询返回数据。
17.2 创建组合查询
可用UNION操作符来组合数条SQL查询。利用UNION,
可给出多条SELECT语句,将它们的结果组合成单个结果集
17.2.1 使用UNION
SELECT vend_id,prod_id,prod_price
FROM products
WHERE prod_price <= 5
UNION
SELECT vend_id,prod_id,prod_price
FROM products
WHERE vend_id IN (1001,1002);
等价
SELECT vend_id,prod_id,prod_price
FROM products
WHERE prod_price <= 5
OR vend_id IN (1001,1002)
17.2.2 UNION规则
UNION必须由两条或两条以上的SELECT语句组成,语句之间用关
键字UNION分隔(因此,如果组合4条SELECT语句,将要使用3个
UNION关键字)。
UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过
各个列不需要以相同的次序列出)。
列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以
隐含地转换的类型(例如,不同的数值类型或不同的日期类型)
UNION从查询结果集中自动去除了重复的行。
如果想返回所有匹配行,可使用UNION ALL而不是UNION。
17.2.4 对组合查询结果排序
SELECT语句的输出用ORDER BY子句排序。在用UNION组合查询时,只
能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。
第十八章 全文本搜索
第十九章 插入数据
19.1 数据插入
NSERT是用来插入(或添加)行到数据库表的。
插入完整的行;
插入行的一部分;
插入多行;
插入某些查询的结果。
19.2 插入完整的行
INSERT INTO customers(cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email)
VALUES(‘pop E.Lap’,
‘100 Main street’,
‘Los Angeles’.
‘CA’,
‘900045’,
‘USA’,
NULL,
NULL);
19.3 插入多个行
INSERT INTO customers(cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email)
VALUES(
‘pop E.Lap’,
‘100 Main street’,
‘Los Angeles’.
‘CA’,
‘900045’,
‘USA’,
NULL,
NULL
),
(
‘pop E.Lap’,
‘100 Main street’,
‘Los Angeles’.
‘CA’,
‘900045’,
‘USA’,
NULL,
NULL
);
第二十章 更新和删除数据
20.1 更新数据 UPDATE
为了更新(修改)表中的数据,可使用 UPDATE 语句。可采用两种方
式使用UPDATE:
更新表中特定行;
更新表中所有行。
UPDATE语句由3部分组成,
要更新的表;
列名和它们的新值;
确定要更新行的过滤条件。
UPDATE customers
SET cust_email = ‘emel@fudd.com’
WHERE cust_id = 10005;
UPDATE语句总是以要更新的表的名字开始。
SET命令用来将新值赋给被更新的列
UPDATE语句以WHERE子句结束,它告诉MySQL更新哪一行。
在更新多个列时,只需要使用单个SET命令,每个“列=值”对之间
用逗号分隔(最后一列之后不用逗号)。
UPDATE customers
SET cust_name = ‘The fudds’,
cust_email = ‘emel@fudd.com’
WHERE cust_id = 10005;
IGNORE 关键字 如果用UPDATE语句更新多行,并且在更新这些
行中的一行或多行时出一个现错误,则整个UPDATE操作被取消
(错误发生前更新的所有行被恢复到它们原来的值)。为即使是发
生错误,也继续进行更新,可使用IGNORE关键字,如下所示:
UPDATE IGNORE customers…
为了删除某个列的值,可设置它为NULL(假如表定义允许NULL值)
UPDATE customers
SET cust_email = NULL
WHERE cust_id = 10005;
20.2 删除数据
为了从一个表中删除(去掉)数据,使用DELETE语句。
可以两种方式使用DELETE:
从表中删除特定的行;
从表中删除所有行。
DELETE FROM customers
WHERE cust_id = 10006;
DELETE 删除整行而不是删除列。为了删除指定的列,请使用 UPDATE 语句。
更快的删除 如果想从表中删除所有行,不要使用DELETE。
可使用 TRUNCATE TABLE 语句,它完成相同的工作,但速度更
快( TRUNCATE实际是删除原来的表并重新创建一个表,而不
是逐行删除表中的数据)。
20.3 更新和删除的指导原则
如果执行UPDATE而不带WHERE子句,则表中每个行都将用新值更新。
类似地,如果执行DELETE语句而不带WHERE子句,表的所有数据都将被删除。
第二十一章 创建和操作表
21.1 创建表
21.1.1 表创建基础
为利用CREATE TABLE创建表,必须给出下列信息:
新表的名字,在关键字CREATE TABLE之后给出;
表列的名字和定义,用逗号分隔。
CREATE TABLE customers
(
cust_id int NOT NULL AUTO_INCREMENT,
cust_name char(50) NOT NULL,
cust_address char(50) NULL,
cust_city char(50) NULL,
cust_state char(50) NULL,
PRIMARY KEY(cust_id)
)ENGINE=InnoDB;
理解NULL 不要把NULL值与空串相混淆。 NULL值是没有值,
它不是空串。如果指定”(两个单引号,其间没有字符),这
在NOT NULL列中是允许的。空串是一个有效的值,它不是无
值。 NULL值用关键字NULL而不是空串指定。
21.1.3 主键再介绍
主键值必须唯一。即,表中的每个行必须具有唯一的主
键值。如果主键使用单个列,则它的值必须唯一。如果使用多个列,则
这些列的组合值必须唯一。
为创建由多个列组成的主键,应该以逗号分隔的列表给出各列名
PRIMARY KEY(order_num,order_item)
主键和NULL值 第1章介绍过,主键为其值唯一标识表中每个
行的列。主键中只能使用不允许NULL值的列。允许NULL值的
列不能作为唯一标识。
21.1.4 使用AUTO_INCREMENT
每个表只允许一个AUTO_INCREMENT列,而且它必须被索引(如,通
过使它成为主键)。
21.2 更新表
为更新表定义,可使用ALTER TABLE语句。
在ALTER TABLE之后给出要更改的表名(该表必须存在,否则将
出错);
所做更改的列表。
ALTER TABLE vendors
ADD vend_phone CHAR(20);
删除刚刚添加的列,可以这样做
ALTER TABLE vendors
DROP COLUMN vend_phone
ALTER TABLE的一种常见用途是定义外键。
ALTER TABLE orderitems
ADD CONSTRAINT fk_orderitems_orders
FOREIGN KEY (order_num) REFERENCES orders(order_num)
为了对单个表进行多个更改,可以使用单条ALTER TABLE语句,
每个更改用逗号分隔。
为了
对单个表进行多个更改,可以使用单条ALTER TABLE语句,每个更改用逗
号分隔。
21.3 删除表
删除表(删除整个表而不是其内容)非常简单,使用DROP TABLE语
DROP TABLE customers;
这条语句删除customers 2表(假设它存在)。删除表没有确认,
也不能撤销,执行这条语句将永久删除该表
21.4 重命名表
使用RENAME TABLE语句可以重命名一个表:
RENAME TABLE customers TO customers2;
RENAME TABLE所做的仅是重命名一个表。可以使用下面的语
句对多个表重命名:
RENAME TABLE customers TO customers2,
customers3 TO customers4,
customers5 TO customers6;
22.2 使用视图
视图用 CREATE VIEW 语句来创建。
使用 SHOW CREATE VIEW viewname ;来查看创建视图的语句。
用 DROP 删除视图,其语法为 DROP VIEW viewname;。
更新视图时,可以先用DROP再用CREATE,也可以直接用CREATE OR
REPLACE VIEW。如果要更新的视图不存在,则第 2 条更新语句会创
建一个视图;如果要更新的视图存在,则第 2 条更新语句会替换原
有视图
22.2.1 利用视图简化复杂的联结
CREATE VIEW productcustomer AS
SELECT cust_name,cust_contact,prod_id
FROM customers,orders,orderitems
WHERE customers.cust_id = orders.cust_id
AND orderitems.order_num=orders.order_num;
这条语句创建一个名为 productcustomers 的视图,它联结三个
表,以返回已订购了任意产品的所有客户的列表
如果执行 SELECT * FROM productcustomers ,将列出订购了任意产品的客户
为检索订购了产品 TNT2 的客户,可如下进行
SELECT * FROM productcustomers
WHERE prod_id = ‘TNT2’
视图极大地简化了复杂SQL语句的使用。利用视图,可一
次性编写基础的SQL,然后根据需要多次使用。
29.1 备份数据
使用命令行实用程序 mysqldump 转储所有数据库内容到某个外部
文件。在进行常规备份前这个实用程序应该正常运行,以便能正
确地备份转储文件。
可用命令行实用程序 mysqlhotcopy 从一个数据库复制所有数据
(并非所有数据库引擎都支持这个实用程序)。
可以使用MySQL的 BACKUP TABLE 或 SELECT INTO OUTFILE 转储所
有数据到某个外部文件。这两条语句都接受将要创建的系统文件
名,此系统文件必须不存在,否则会出错。数据可以用 RESTORE
TABLE 来复原。
首先刷新未写数据: 为了保证所有数据被写到磁盘(包括索引
数据),可能需要在进行备份前使用 FLUSH TABLES 语句
29.4 查看日志文件
MySQL维护管理员依赖的一系列日志文件。主要的日志文件有以下
几种。
错误日志。它包含启动和关闭问题以及任意关键错误的细节。此
日志通常名为 hostname.err ,位于 data 目录中。此日志名可用
–log-error 命令行选项更改。
查询日志。它记录所有MySQL活动,在诊断问题时非常有用。此
日志文件可能会很快地变得非常大,因此不应该长期使用它。此
日志通常名为 hostname.log ,位于 data 目录中。此名字可以用
–log 命令行选项更改。
二进制日志。它记录更新过数据(或者可能更新过数据)的所有
语句。此日志通常名为 hostname-bin ,位于 data 目录内。此名字
可以用 –log-bin 命令行选项更改。注意,这个日志文件是MySQL
5中添加的,以前的MySQL版本中使用的是更新日志。
缓慢查询日志。顾名思义,此日志记录执行缓慢的任何查询。这
个日志在确定数据库何处需要优化很有用。此日志通常名为
hostname-slow.log , 位 于 data 目 录 中 。 此 名 字 可 以 用
–log-slow-queries 命令行选项更改。
在使用日志时,可用 FLUSH LOGS 语句来刷新和重新开始所有日志文
件。