概述
引擎(Engine):
InnoDB
:支持事务,但不支持全文本搜索
MyISAM
:支持全文本搜索,但不支持事务
Memory
:功能同MyISAM,但存储在内存
查询
NULL
:表示没有值,与空字符串不同;
Search Pattern
:搜索模式,即搜索条件;
基本
SELECT prod_name FROM products;
SELECT prod_id, prod_name, prod_price FROM products;
SELECT * FROM products;
SELECT DISTINCT vend_id FROM products; # 去掉重复行
SELECT prod_name FROM products LIMIT 5; # 返回最多5行
SELECT prod_name FROM products LIMIT 5,5; # 从row5开始计算最多5行
SELECT prod_name FROM products LIMIT 5 OFFSET 5; # 同上(MySQL5)
SELECT products.prod_name FROM crashcourse.products; # 限定列名和表名
排序
SELECT prod_name FROM products ORDER BY prod_name;
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price, prod_name; # 先用price排序,price相同的再用name排序
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC; # 降序(默认升序,ASC)
过滤
WHERE
过滤行,HAVING
过滤分组
SELECT vend_id, prod_name FROM products WHERE vend_id != 1003; # where子句操作符
SELECT prod_name, prod_price FROM products WHERE prod_price BETWEEN 5 AND 10; # 5~10
SELECT prod_name FROM products WHERE prod_price IS NULL;
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id=1003 AND prod_price<=10;
SELECT prod_name, prod_price FROM products WHERE vend_id=1002 OR vend_id=1003;
SELECT prod_name, prod_price FROM products WHERE (vend_id=1002 OR vend_id=1003) AND prod_price>=10; # AND优先级更高
SELECT prod_name, prod_price FROM products WHERE vend_id IN (1002,1003) ORDER BY prod_name; # vend_id等于1002和1003
SELECT prod_name, prod_price FROM products WHERE vend_id NOT IN (1002,1003) ORDER BY prod_name;
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%'; # %匹配任意多个字符(包括0个)(LIKE必须用通配符)
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '_ ton anvil'; # _匹配1个字符
SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000';
函数
Calculated Fields
:计算字段,检索出经转换、计算或格式化过的数据
Aggregate Function
:聚集函数,获取表的汇总信息
# 计算字段(field)
SELECT Concat(vend_name, ' (', vend_country, ')') FROM vendors ORDER BY vend_name; # 拼接:ACME (USA)
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems; # 计算字段、别名
# 函数
SELECT vend_name, Upper(vend_name) AS vend_name_upcase FROM vendors ORDER BY vend_name;
SELECT cust_name, cust_contact FROM customers WHERE Soundex(cust_contact)=Soundex('Y Lie'); # 匹配发音类似:Y Lee
SELECT cust_id, order_num FROM orders WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30';
# 聚集函数(aggregate function)
SELECT AVG(prod_price) AS avg_price FROM products; # 计算平均值(忽略列值为NULL的行)
SELECT COUNT(*) AS num_cust FROM customers; # 统计总行数(忽略列值为NULL的行)
SELECT MAX(prod_price) AS max_price FROM products;
SELECT SUM(item_price*quantity) AS total_price FROM orderitems WHERE order_num=20005; # 统计总和
分组(Group)
使用GROUP BY
和HAVING
进行分组及过滤,用于对内容划分后再汇总
SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id; # 对每个vend_id分别统计
SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price>=10 GROUP BY vend_id HAVING COUNT(*)>=2; # where过滤行,having过滤分组
SELECT子句顺序
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
LIMIT
子查询(Subquery)
嵌套在查询中的查询
Correlated Subquery
:相关子查询,涉及外部查询的子查询
# 利用子查询过滤
SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id='TNT2');
# 利用计算字段使用子查询
SELECT cust_name,
cust_state,
(SELECT COUNT(*) FROM orders WHERE orders.cust_id=customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;
联结(Join)
关联表查询
Foreign Key
:外键,表中的一列包含另一个表的主键值
笛卡尔积
:没有联结条件的表关系返回结果为笛卡尔积,即结果行数为两张表行数的乘积
Inner Join
:内部联结,默认联结,仅返回关联行
Outer Join
:外部联结,返回结果包括无关联行
自联结
:联结同一张表(两个实例),可替代基于同一张表的子查询;
SELECT vend_name, prod_name, prod_price FROM vendors, products WHERE vendors.vend_id=products.vend_id; # 等值联结(equijoin)
SELECT vend_name, prod_name, prod_price FROM vendors INNER JOIN products WHERE vendors.vend_id=products.vend_id; # 效果同上,内部联结(默认)
# 自联结
SELECT prod_id, prod_name FROM products WHERE vend_id=(SELECT vend_id FROM products WHERE prod_id='DTNTR'); # 子查询
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 customers.cust_id, orders.order_num FROM customers LEFT OUTER JOIN orders ON customers.cust_id=orders.cust_id;
SELECT customers.cust_id, orders.order_num FROM customers RIGHT OUTER JOIN orders ON customers.cust_id=orders.cust_id;
组合查询(Union)
合并多个查询结果
SELECT ...
UNION # UNION ALL(不去除重复行)
SELECT ...
ORDER BY ... # 对最终结果排序
全文本搜索(Fulltext Search)
全文本搜索,仅MyISAM
引擎支持,创建表时用FULLTEXT(column)
对指定列进行索引后才可以进行全文本搜索
Query Expansion
:查询扩展,可放宽搜索范围;进行两次搜索,在第一次搜索结果上找到“可能有用的”单词,加入搜索条件后再搜索一遍;
Boolean Mode
:布尔搜索,没有FULLTEXT
索引也能使用
CREATE TABLE productnotes (
note_id int NOT NULL AUTO_INCREMENT,
prod_id char(10) NOT NULL,
note_date datetime NOT NULL,
note_test text NULL,
PRIMARY KEY(note_id),
FULLTEXT(note_text) # 对指定列进行索引
) ENGINE=MyISAM; # 支持全文搜索的引擎
SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit');
SELECT note_text FROM productnotes WHERE note_text LIKE '%rabbit%'; # 同上,但是全文本搜索会优先返回匹配程度高的行
SELECT note_text, Match(note_text) Against('rabbit') AS rank FROM productnotes; # rank为匹配程度(等级值)
# 查询扩展
SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit' WITH QUERY EXPANSION);
# 布尔文本搜索
SELECT note_text FROM productnotes WHERE Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE); # 排除包含rope*的行
SELECT note_text FROM productnotes WHERE Match(note_text) Against('+rabbit +bait' IN BOOLEAN MODE); # 同时包含两个
SELECT note_text FROM productnotes WHERE Match(note_text) Against('"rabbit bait"' IN BOOLEAN MODE); # 包含"rabbit bait"
修改记录
INSERT INTO customers VALUES ('aaa', 'bbb', 'ccc');
INSERT INTO customers(cust_name, cust_city, cust_email) VALUES ('aaa','bbb','ccc');
INSERT INTO customers VALUES (...),(...); # 插入多行
UPDATE customers SET cust_email='xxx' WHERE cust_id=10005;
UPDATE customers SET cust_name='aaa', cust_email='xxx' WHERE cust_id=10005;
UPDATE IGNORE customers SET cust_email='xxx' WHERE cust_id=10005; # 即使某行发生错误也继续执行(不Ignore,其中一行出错则全部取消)
UPDATE customers SET cust_email='NULL'; # NULL不同于空字符串
DELETE FROM customers WHERE cust_id=10006;
表(Table)
ALERT TABLE vendors ADD vend_phone CHAR(20);
ALERT TABLE vendors DROP COLUMN vend_phone;
ALERT TABLE orderitems ADD CONSTRAINT fk_orderitems_orders FOREIGN KEY (order_num) REFERENCES orders (order_num); # 定义外键
DROP TABLE customers;
RENAME TABLE customer2 TO customers;
视图(View)
类似宏的概念,就是一个SQL查询的别名
CREATE VIEW customeremaillist AS
SELECT cust_id, cust_name, cust_email FROM customers WHERE cust_email IS NOT NULL;
SHOW CREATE VIEW viewname; # 查看view语句
DROP VIEW viewname;
CREATE OR REPLACE VIEW ...
存储过程(Stored Procedure)
类似函数的概念,可传入参数并返回变量
CREATE PROCEDURE productpricing()
BEGIN
SELECT Avg(prod_price) AS priceaverage FROM products;
END;
CALL productpricing();
# 使用参数
CREATE PROCEDURE ordertotal(
IN onumber INT,
OUT ototal DECIMAL(8,2)
)
BEGIN
SELECT Sum(item_price*quantity) FROM orderitems WHERE order_item=onumber
INTO otal;
END;
CALL ordertotal(20005, @total); # 不返回数据,仅返回变量供后面使用
SELECT @total;
DROP PROCEDURE productpricing;
SHOW CREATE PROCEDURE ordertotal;
SHOW PROCEDURE STATUS;
游标(Cursor)
只能用于PROCEDURE
,可对搜索结果逐行FETCH
后进行处理
CREATE PROCEDURE processorders()
BEGIN
DECLARE o INT;
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
OPEN ordernumbers;
FETCH ordernumbers INTO o;
CLOSE ordernumbers;
END;
触发器(Trigger)
当INSERT
,UPDATE
,DELETE
发生时,可自动执行SQL语句
可在事件AFTER
或BEFORE
触发,每个表每个事件只能有一个Trigger,因此每个表最多只有6个
Trigger
CREATE TRIGGER newproduct AFTER INSERT ON products FOR EACH ROW SELECT 'Product added';
DROP TRIGGER newproduct;
CREATE TRIGGER neworder AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num;
CREATE TRIGGER deleteorder BEFORE DELETE ON orders FOR EACH ROW
BEGIN
INSERT INTO archive_orders(order_num, order_date, cust_id) VALUES(OLD.order_num, OLD.order_date, OLD.cust_id);
END;
CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors FOR EACH ROW SET NEW.vend_state=Upper(NEW.vend_state);
事务(Transaction)
为维护数据完整性,成批操作要么完全执行,要么完全不执行
transaction
:一组SQL语句
rollback
:撤销执行
commit
:将未存储的SQL语句结果写入数据库
savepoint
:保留点,作用类似Label,可roolback到指定savepoint,否则roolback到最开始
autocommit
:是否自动提交变更——无论有没有commit;针对每个连接,而非数据库
START TRANSACTION;
SAVEPOINT delete1;
...
ROLLBACK TO delete1;
...
COMMIT
SET autocommit=0;
字符集
collation
:校对,即字符排序规则;比如区分大小写、重音、假名、全半角等等
_ci
大小写不敏感,_cs
大小写敏感,_bin
二进制
设置位置:Client, Connection, Database, Results, Server, System
SHOW CHARACTER SET;
SHOW COLLATION;
SHOW VARIABLES LIKE 'character%';
SHOW VARIABLES LIKE 'collation%';
CREATE TABLE mytable(
column1 INT,
column2 VARCHAR(10),
column3 VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci
) DEFAULT CHARACTER SET hebrew
COLLATE hebrew_general_ci;
SELECT * FROM customers ORDER BY lastname, firstname COLLATE latin1_general_cs;
ALERT TABLE db_allot CONVERT TO CHARACTER SET latin1 COLLATE latin1_bin;
账户
user@host
:user@%
表示不管主机名
database.table
:*.*
表示所有
CREATE USER ben IDENTIFIED BY 'p@ssw0rd';
RENAME USER ben TO forta;
DROP USER forta;
SHOW GRANTS FOR forta; # 显示“USAGE”表示没有任何权限
GRANT SELECT ON crashcourse.* TO forta; # db.table
REVOKE SELECT ON crashcourse.* FROM forta;
SET PASSWORD FOR forta=Password('p@ssw0rd');
SET PASSWORD=Password('p@ssw0rd'); # 当前用户
维护
# 导出
mysqldump -u USER -p DB > FILE # 导出整个数据库
mysqldump -u USER -p DB TABLE > FILE # 导出表
mysqlhotcopy --user=USER --password=PASSWORD -q DB DIR
# 导入
source FILE; # 控制台导入
mysql -u USER -p DB < FILE
FLUSH TABLES; # 将缓存写入磁盘
# 检查
ANALYZE TABLE orders;
CHECK TABLE orders, orderitems;
参考
- Ben Forta. 《MySQL必知必会》