2016/2/21
数据库:保存有组织的数据的容器(通常是一个文件或一组文件)
数据库管理系统(DBMS):用于访问数据库。
表:某种特定类型数据的结构化清单。相同的数据库中表的名字是唯一的
模式:关于数据库和表的布局及特性的信息。可以用来描述数据库中特定的表以及整个数据库。
列:表中的一个字段,所有表都是由一个或多个列组成。
数据类型:所容许的数据的类型。每个表列都有相应的数据类型,它限制(或容许)该列中存储的数据。
行:表中的一个记录
主键:一列(或一组列),其值能够唯一区分表中每个行。
主键值的几个规则。
SQL:结构化查询语言。专门用来与数据库通信的语言。
2016/2/22
DBMS分为两类:
基于共享文件系统的DBMS
基于客户机-服务器的DBMS
USE关键字:选择一个数据库。必须先使用USE打开数据库,才能读取其中的数据。
返回可用数据库的一个列表
SHOW DATABASES;
返回当前选择的数据库内可用表的列表。
SHOW TABLES;
也可用来显示表列。
SHOW COLUMNS FROM customers;
快捷方式:
DESCRIBE customers;
显示允许的SHOW命令
HELP SHOW;
SELECT语句:从表中检索一个或多个数据列。
SELECT prod_name #列名(列名间加上逗号可以检索多个列;使用通配符(*)可以检索所有列,并能检索出名字未知的列) FROM products; #从中检索数据的表名
SQL语句不区分大小写,多数开发人员喜欢对关键字使用大写,便于阅读和调试。
SELECT DISTINCT vend_id #DISTINCT,指示只返回不同的值,它应用于所有列。 FROM products;
SELECT prod_name FROM products LIMIT 5; #指示MySQL返回不多于5行。
SELECT prod_name FROM products LIMIT 3, 4; #指示MySQL返回从行3开始的4行。
替代语法:
LIMIT 4 OFFSET 3;
行0:表示第一行。
使用完全限定的表名,列名。
SELECT products.prod_name FROM crashcourse.products;
子句的概念:如SELECT语句的FROM子句。
ORDER BY子句指示MySQL对prod_name列以字母顺序排序。
SELECT prod_name FROM products ORDER BY prod_name;
也可通过非选择列进行排序。
检索3个列,对其中两个列进行排序。
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price, prod_name;
DESC关键字:指定降序排序。
ASC:指定升序排序(默认)。
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC;
DESC关键字只应用到直接位于其前面的列名上。
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name;
在对文本性的数据进行排序时,A与a是否相同,取决于数据库如何设置。
子句的使用顺序:FROM子句->WHERE子句->ORDER BY子句->LIMIT子句
WHERE子句:
SELECT prod_price, prod_name FROM products WHERE prod_price = 2.50;
字符串使用‘ ’,单引号用于限定字符串。
MySQL在执行匹配时默认不区分大小写。
SELECT prod_price, prod_name FROM products WHERE prod_name = 'fuses';
<
<=
<> 不等于
!= 不等于
BETWEEN操作符
SELECT prod_price, prod_name FROM products WHERE prod_price BETWEEN 5 AND 10;
NULL 无值,它与字段包含0、空字符串或仅仅包含空格不同。
SELECT prod_name FROM products WHERE prod_price IS NULL;
NULL值的行,表示未知,数据库不知道它们是否匹配,所以在匹配过滤或不匹配过滤时不返回它们。
AND操作符:用在WHERE子句中。计算优先级大于OR操作符。
OR操作符
圆括号可对相应操作符分组。使用圆括号没有坏处,还能消除歧义。
IN操作符(与OR操作符完成相同的功能)
WHERE子句中用来指定要匹配值的清单的关键字。
SELECT prod_price, prod_name FROM products WHERE vend_id IN (1002,1003) ORDER BY prod_name;
NOT操作符
WHERE子句中用来否定后跟条件的关键字。
SELECT prod_price, prod_name FROM products WHERE vend_id NOT IN (1002,1003) ORDER BY prod_name;
通配符:用来匹配值的一部分的特殊字符。可在搜索模式中任意位置使用,并且可以使用多个通配符。
搜索模式:由字面值、通配符或两者组合构成的搜索条件。
LIKE操作符:它是谓词,指示MySQL,后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较。
百分号(%)通配符
表示任何字符出现任意次数。0次、1次、多次。
% 不能匹配 NULL。
下划线(_)通配符
匹配单个字符。
通配符使用技巧
不要过度使用通配符。花费时间更长。
除非绝对必要,否则不要把通配符用在搜索模式的开始出。
仔细注意通配符的位置。不要放错地方。
正则表达式控制数据过滤
REGEXP后所跟的东西作为正则表达式处理
SELECT prod_name FROM products WHERE prod_name REGEXP '1000' ORFER BY prod_name;
. 匹配任意一个字符。
SELECT prod_name FROM products WHERE prod_name REGEXP '.1000' ORFER BY prod_name;
LIKE与REGEXP的区别:
LIKE:匹配整个列
REGEXP:在列值内进行匹配。使用^和$定位符才能匹配整个列。
BINARY关键字:使MySQL中的正则表达式匹配区分大小写。
进行OR匹配
SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000' ORFER BY prod_name;
匹配几个字符之一
SELECT prod_name FROM products WHERE prod_name REGEXP '[123] Ton' ORFER BY prod_name;
[123]定义一组字符,它的意思是匹配1或2或3.
可以写成[1|2|3],但[]不能省略。
[^123]匹配除1 2 3 外的任何东西。
[1-5]匹配范围
[a-z]
匹配特殊字符:必须用\\为前导(转义)。如\\- \\. 。(MySQL自己解释一个\,正则表达式库解释另一个)
\\也可用来引用元字符(具有特殊含义的字符)
\\\匹配\本身。
2016/2/23
第十章创建计算字段
字段:计算字段
拼接:将值联结到一起构成单个值。
使用Concat()函数来拼接两个列。
SELECT Concat(vend_name, ' (', vend_country, ')') FROM vendors ORDER BY vend_name;
RTrim()函数:删除数据右侧多余的空格。
LTrim()函数:删除数据左侧多余的空格。
Trim()函数:删除数据左右两侧多余的空格。
SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')') FROM vendors ORDER BY vend_name;
新计算列没有名字,它只是一个值。未命名的列不能用于客户机应用,客户机没有办法引用它。
使用别名,解决这个问题。
SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;
别名(导出列)的其他用途:重命名。
执行算数计算
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems WHERE order_num = 20005;
SELECT可以省略FROM子句以便简单地访问和处理表达式。
第十章使用数据处理函数
文本处理函数
SELECT vend_name, Upper(vend_name) AS vend_name_upcase FROM vendors ORDER BY vend_name;
使用Soundex()函数,匹配发音类似的值。
SELECT cust_name, cust_contact FROM customers WHERE Soundex(cust_contact) = Soundex('Y Lie');
日期和时间处理函数
一般,应用程序不使用用来存储日期和时间的格式,日期和时间函数总是被用来读取、统计和处理这些值。
SELECT cust_id, order_num FROM orders WHERE order_date = '2005-09-01';
Date() 日期。
SELECT cust_id, order_num FROM orders WHERE Date(order_date) = '2005-09-01';
Time() 时间
SELECT cust_id, order_num FROM orders WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30';
SELECT cust_id, order_num FROM orders WHERE Year(order_date) 2005 AND Month(order_date) = 9;
数值处理函数
第十二章 汇总数据
聚集函数:运行在行组上,计算和返回单个值的函数。
AVG函数:确定特定数值列的平均值,列名作为函数参数。忽略列值为NULL的行。
SELECT AVG(prod_price) AS avg_price FROM products;
AVG()确定特定列或行的平均值。
SELECT AVG(prod_price) AS avg_price FROM products;
COUNT函数
对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
SELECT COUNT(*) AS num_cust FROM customers;
如果指定列名,则指定列的值为空的行被COUNT()函数忽略。
SELECT COUNT(cust_email) AS num_cust FROM customers;
MAX()函数:返回指定列中的最大值。要求指定列名。忽略列值为NULL的行。
MIN()函数
SUM()函数:返回指定列值的和(总计)。
SELECT SUM(quantity) AS total_price FROM orderitems WHERE order_num = 20005;
SUM()函数也可用来合计计算值
SELECT SUM(item_price*quantity) AS total_price FROM orderitems WHERE order_num = 20005;
聚集不同值。
DISTINCT参数。缺省时,默认指定了ALL参数。
SELECT AVG(DISTINCT prod_price) AS avg_price FROM products; WHERE vend_id = 1003;
组合聚集函数:单条SELECT语句执行4个聚集计算。
第十三章分组数据
GROUP BY子句指示MySQL分组数据,然后对每个分组而不是整个结果集进行聚集。
SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id;
HAVING子句(与WHERE子句的区别:WHERE过滤行,而HAVING过滤分组)
WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。
SELECT cust_id, COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2;
一般在使用GROUP BY子句时,应该也给出ORDER BY子句。这是保证数据正确排序的唯一方法。
SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >= 50 ORDER BY ordertotal;
SELECT子句顺序 (pdf 100页)
第十四章 使用子查询
查询:任何SQL语句都是查询。但此术语一般指SELECT语句。
SELECT order_num FROM orderitems WHERE prod_id = 'TNT2'; SELECT cust_id FROM orders WHERE order_num IN (20005,20007);
把第一个查询变为子查询组合两个查询
SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id = 'TNT2');
在SELECT语句中,子查询总是从内向外处理。
子查询一般与IN操作符结合使用,但也可以用于测试等于(=)、不等于(<>)等。
作为计算字段使用子查询
SELECT cust_name, cust_state, (SELECT COUNT(*) FROM orders WHERE orders.cust_id = customers.cust_id) AS orders FROM customers ORDER BY cust_name;
使用完全限定列名。
WHERE orders.cust_id = customers.cust_id) AS orders
相关子查询:设计外部查询的子查询。
任何时候只要列名可能有多义性,就必须使用这种语法(表名和列名由一个句点分隔)。
逐渐增加子查询来建立查询:首先,建立和测试最内层的查询。然后,用硬编码数据建立和测试外层查询,并且仅在确认它正常后才嵌入子查询。
子查询最常见的使用是在WHERE子句的IN操作符中,以及用来填充计算列。
第十五章联结表
关系表:关系表的设计就是要保证把信息分解成多个表,一类数据一个表。各表通过某些常用的值(即关系设计中的关系)互相关联。
主键
外键:某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。
可伸缩性:能够适应不断增加的工作量而不失败。设计良好的数据库或应用程序称之为可伸缩性好。
联结:用来在一条SELECT语句中关联表。联结不是物理实体,它在实际的数据库表中不存在,它存在于查询的执行当中。
(联结是SQL中最重要最强大的特性。)
2016/2/24
创建联结
SELECT vend_name, prod_name, prod_price FROM vendors, products WHERE vendors.vend_id = products.vend_id ORDER BY vend_name, prod_name;
prod_name, prod_price在表products中,vend_name在表vendors中。
WHERE子句过滤,后面跟的是联结条件。
笛卡尔积:由没有联结条件的表关系返回的结果为笛卡尔积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
SELECT vend_name, prod_name, prod_price FROM vendors, products ORDER BY vend_name, prod_name;
返回的数据用每个供应商匹配了每个产品。
所有联结都应由WHERE子句。
叉联结。
等值联结:基于两个表之间的相等测试。也称为内部联结
SELECT vend_name, prod_name, prod_price FROM vendors INNER JOIN products ON vendors.vend_id = products.vend_id;
INNER JOIN指定两个表之间的关系,ON指定联结条件。
联结多个表。
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;
性能考虑:联结的表越多,性能下降越厉害。
用联结代替子查询
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';
第十六章创建高级联结
别名除了用于列名和计算字段外,SQL还允许给表名起别名。
给表名起别名的作用:
缩短SQL语句;
允许在单条SELECT语句中多次使用相同的表。
缩短SQL语句;
SELECT cust_name, cust_contact FROM customers AS c, orders AS o, orderitems AS oi WHERE c.cust_id = o.cust_id AND oi.order_num = o.order_num AND prod_id = 'TNT2';
表别名只在查询执行中使用。与列别名不一样,表别名不返回到客户机。
自联结
SELECT p1.prod_id, p1.prod_name FROM products AS p1, products AS p2 WHERE p1.vend_id = p2.vend_id AND p2.prod_id = 'DTNTR';
子查询
SELECT prod_id, prod_name FROM products WHERE vend_id = (SELECT vend_id FROM products WHERE prod_id = 'DTNTR');
无论何时对表进行联结,应该至少有一个列出现在不止一个表中(被联结的列)。
自然联结排除多次出现,使每个列只返回一次。
对表使用通配符(SELECT *),选择那些唯一的列。对所有其他表的列使用明确的子集来完成。
SELECT c.*, o.order_num, o.order_date, oi.prod_id, oi.quantity, oi.item_price FROM customers AS c, orders AS o, orderitems AS oi WHERE c.cust_id = o.cust_id AND oi.order_num = o.order_num AND prod_id = 'FB';
外部联结:联结包含了那些在相关表中没有关联的行。
检索所有客户,包括那些没有订单的客户。
SELECT customers.cust_id, orders.order_num FROM customers LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id;
OUTER JOIN指定联结的类型,
必须使用LEFT或RIGHT关键字指定包括其所有行的表。(RIGHT:OUTER JOIN 右边的表,LEFT:OUTER JOIN左边的表)
使用带聚集函数的联结
SELECT customers.cust_name, customers.cust_id, COUNT(orders.order_num) AS num_ord FROM customers INNER JOIN orders ON customers.cust_id = orders.cust_id GROUP BY customers.cust_id;
联结使用的要点
1)注意联结类型:内部联结、外部联结
2)使用正确的联结条件
3)应该总是提供一个联结条件,否则会得出笛卡尔积。
第十七章组合查询
并(union)/复合查询:执行多个查询,并将结果作为单个查询结果返回。
需要使用组合查询的两种基本情况:
1)在单个查询中从不同的表返回类似结构的数据;
2)对单个表执行多个查询,按单个查询返回数据。
UNION的规则
2016/2/25
UNION从查询结果集中自动去除重复的行。
UNION ALL:返回所有匹配行,不取消重复的行。
在用UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。
用来排序所有SELECT语句返回的所有结果。
使用UNION的组合查询可以应用不同的表。
第十八章全文本搜索
Match()和Against()函数
查询扩展
布尔方式
第十九章插入数据
INSERT语句:插入(或添加)行到数据库表。
插入的几种方式:
1)插入完整的行;
2)插入行的一部分;
3)插入多行;
4)插入某些查询的结果。
INSERT INTO customers VALUES(NULL, 'Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', NULL, NULL);
对每个列必须提供一个值,如果某个列没有值,应该使用NULL,
各个列必须以它们在表定义中出现的次序填充。
编写依赖于特定列次序的SQL语句是很不安全的。
编写INSERT语句的更安全的方法:(更烦琐)(使用列的列表)
INSERT INTO customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) VALUES('Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', NULL, NULL);
不要使用没有明确给出列的列表的INSERT语句。
省略列:省略的列必须满足以下某个条件。
1)该列为定义允许NULL值。
2)在表定义中给出默认值。
LOW_PRIORITY,指示MySQL降低INSERT语句的优先级。
单条语句插入多个值:(列名相同)
插入检索出的数据:INSERT SELECT
第二十章更新和删除数据
UPDATE语句:更新(修改)表中的数据
使用UPDATE的两种方法:
1)更新表中特定行;
2)更新表中所有行;
UPDATE customers SET cust_email = 'elmer@fudd.com' WHERE cust_id = 10005;
WHERE过滤条件不能少,否则会更新整个表。
更新多个列
UPDATE customers SET cust_name = 'The Fudds', cust_email = 'elmer@fudd.com' WHERE cust_id = 10005;
IGNORE关键字:UPDATE语句中即使发生错误,也继续更新。
删除某个列的值,可设置它为NULL。
DELETE语句:删除数据。
1)从表中删除特定的行;(使用WHERE)
2)从表中删除所有行。
DELETE FROM customers WHERE cust_id = 10006;
DELETE语句删除的是行,为了删除指定的列,使用UPDATE语句。
TRUNCATE TABLE语句:删除原来的表并重新创建一个表。速度比使用DELETE删除表中所有行块。
使用UPDATE和DELETE的四个习惯。
MySQL没有撤销按钮,使用UPDATE和DELETE时多加小心。