问题1:通配符的问题
% 多字符匹配
_ 单字符匹配
正如所见,MySQL的通配符很有用。但这种功能是有代价的:通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给出一些使用通配符要记住的技巧。
不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
仔细注意通配符的位置。如果放错地方,可能不会返回想要的数
问题2:搭配正则表达式
快捷使用--字符类


问题3:函数
1.拼接字段
MySQL的不同之处 多数DBMS使用+或11来实现拼接,MySQL则使用Concat()函数来实现。当把SQL语句转换成MySQL语句时一定要把这个区别铭记在心。
2.文本处理
默认不区分大小写,区分大小写:Binary 'L'


3.日期时间

4.数值处理

5.聚集函数

AVG
AVG()只能用来确定特定数值列的平均值,而且列名必须作为函数参数给出。为了获得多个列的平均值,必须使用多个AVG()函数。NULL值 AVG()函数忽略列值为NULL的行。
COUNT

问题4:分组
GROUP BY

使用ROLLUP 使用WITHROLLUP关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值。
HAVING
类似于WHERE的功能,对分组结果进行筛选。
所有关键字的顺序

问题5:联结
1.使用子查询
2.内联结(可以使用WHERE,也可使用INNER JOIN ... ON)
3.自联结
4.外部联结
问题6:组合
组合合并重复 UNION
组合不合并重复 UNION ALL
问题7:全文本搜索
为了进行全文本搜索,须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表列进行适当设计后,MySQL会自动进行所有的索引和重新索引。 在索引之后,SELECT可与Match()和Against()一起使用以实际执行搜索。
传递给Match()的值必须与FULLTEXT()定义中的相同。如果指定多个列,则必须列出它们(而且次序正确)。
优先级问题
两个行都包含词rabbit,但包含词rabbit作为第3个词的行的等级比作为第20个词的行高。这很重要。全文本搜索的一个重要部分就是对结果排序。具有较高等级的行先返回(因为这些行很可能是你真正想要的行)。
如果指定多个搜索项,则包含多数匹配词的那些行将具有比包含较少词(或仅有一个匹配)的那些行高的等级值。
扩展查询
with query expansion
boolean文本查询
即使没有FULLTEXT索引也可以使用

SELECT note_text from productnotes where MATCH(note_text) AGAINST ('+rabbit +bait' IN BOOLEAN MODE);
注意点
在索引全文本数据时,短词被忽略且从索引中排除。短词定义为那些具有3个或3个以下字符的词(如果需要,这个数目可以更改)。
MySQL带有一个内建的非用词(stopword)列表,这些词在索引全文本数据时总是被忽略。如果需要,可以覆盖这个列表。
许多词出现的频率很高,搜索它们没有用处(返回太多的结果)。因此,MySQL规定了一条50%规则,如果一个词出现在50%以上的行中,则将它作为一个非用词忽略。50%规则不用于 IN BOOLEAN MODE 。
忽略词中的单引号。例如, don't 索引为 dont 。
不具有词分隔符(包括日语和汉语)的语言不能恰当地返回全文本搜索结果。
问题8:增删改总结
插入检索出的数据
INSERT INTO customers (
cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country
) SELECT
cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country
FROM
customers_copy
WHERE
cust_id = 10007;
更新
UPDATE customers
SET cust_email = 'elmer@fudd.com'
WHERE
cust_id = 10005;
自动进行事务回滚,不想要使用UPDATE IFNORE
增删改的原则
除非确实打算更新和删除每一行,否则绝对不要使用不带 WHERE子句的 UPDATE 或 DELETE 语句。
保证每个表都有主键(如果忘记这个内容,请参阅第15章),尽可能像 WHERE 子句那样使用它(可以指定各主键、多个值或值的范围)。
在对 UPDATE 或 DELETE 语句使用 WHERE 子句前,应该先用 SELECT 进行测试,保证它过滤的是正确的记录,以防编写的 WHERE 子句不正确。
查询的可持久
SELECT * FROM orders INTO OUTFILE 'D:/data.txt'
问题9:Mysql的数据类型
- 串数据类型

大致分为定长,变长
不管使用何种形式的串数据类型,串值都必须括在引号内(通常单引号更好)。电话号码和邮政编码不应该存储在数值字段中。
- 数值数据类型
大致分为有符号,无符号的,默认情况为有符号,但如果你知道自己不需要存储负值,可以使用UNSIGNED关键字,这样做将允许你存储两倍大小的值。

数值不应该在引号内。
- 日期和时间数据类型

- 二进制数据类型
二进制数据类型可存储任何数据(甚至包括二进制信息),如图像、多媒体、字处理文档等

问题10:MySQL的引擎

外键不能跨引擎
问题11:使用视图
视图的规则和限制

视图的创建删除和更改

视图最好用在查找操作,而非更新:
如果视图定义中有以下操作,则不能进行视图的更新:
分组(使用GROUP BY和HAVING);联结;子查询;并;聚集函数(Min()、Count()、Sum()等);DISTINCT;导出(计算)列。
问题12:存储过程--函数
举例1:
CREATE PROCEDURE productpricing(
OUT pl DECIMAL(8,2),
OUT ph DECIMAL(8,2),
OUT pa DECIMAL(8,2)
)
BEGIN
SELECT MIN(prod_price)
INTO pl
FROM products;
SELECT max(prod_price)
INTO ph
FROM products;
SELECT avg(prod_price)
INTO pa
FROM products;
END;
CAll productpricing(@pricelow,@pricehigh,@priceaverage)
SELECT @pricelow,@pricehigh,@priceaverage;
举例2:
CREATE PROCEDURE ordertotal (
IN onumber INT,
IN taxable BOOLEAN,
OUT ototal DECIMAL (8, 2)
) COMMENT 'Obtain order total, optionally adding tax'
BEGIN
-- Declare variable for total
DECLARE total DECIMAL (8, 2);
-- Declare tax percentage
DECLARE taxrate INT DEFAULT 6;
-- Get the order total
SELECT
Sum(item_price * quantity)
FROM
orderitems
WHERE
order_num = onumber
INTO total;
-- Is this taxable?
IF taxable THEN
-- Yes, so add taxrate to the total
SELECT
total + (total / 100 * taxrate) INTO total;
END IF;
SELECT total INTO ototal;
END;
call ordertotal(20005,0,@total);
SELECT @total;
SHOW PROCEDURE STATUS LIKE 'ordertotal';
问题13:游标
有时,需要在检索出来的行中前进或后退一行或多行。这就是使用游标的原因。游标(cursor)是一个存储在MySQL服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改。

在一个游标被打开后,可以使用FETCH语句分别访问它的每一行。 FETCH指定检索什么数据(所需的列),检索出来的数据存储在什么地方。它还向前移动游标中的内部行指针,使下一条FETCH语句检索下一行(不重复读取同一行)。
举例:
CREATE TABLE IF NOT EXISTS ordertotals
(order_num INT, total DECIMAL(8,2));
CREATE PROCEDURE processorders ()
BEGIN
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL (8, 2);
DECLARE ordernumbers CURSOR FOR SELECT
order_num
FROM
orders;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
SET done = 1;
OPEN ordernumbers;
REPEAT
FETCH ordernumbers INTO o;
CALL ordertotal (o, 1, t);
INSERT INTO ordertotals (order_num, total)
VALUES(o, t);
UNTIL done END REPEAT;
CLOSE ordernumbers;
END;
call processorders ();
SELECT * FROM ordertotals;
问题14:触发器
在创建触发器时,需要给出4条信息:
唯一的触发器名;
触发器关联的表;
触发器应该响应的活动( DELETE 、 INSERT 或 UPDATE );
触发器何时执行(处理之前或之后)。
触发器用 CREATE TRIGGER 语句创建。
只有表才支持触发器,视图不支持(临时表也不支持)。每个表最多支持6个触发器(每条 INSERT 、 UPDATE和 DELETE 的之前和之后)
CREATE TRIGGER newproduct AFTER INSERT ON products FOR EACH ROW SELECT
'Product added' INTO @ee;
-- mysql5之后,不支持返回值,可以把这个值导入变量中
INSERT INTO `crashcourse`.`products` (
`prod_id`,
`vend_id`,
`prod_name`,
`prod_price`,
`prod_desc`
)
VALUES
(
'ANV031',
'1001',
'2 ton anvil',
'14.99',
'2 ton anvil, black, complete with handy hook and carrying case'
);
问题15:事务处理
START TRANSACTION ---开始事务处理
MySQL的ROLLBACK命令用来回退(撤销)MySQL语句
举例:
SELECT * FROM ordertotals;
START TRANSACTION;
DELETE FROM orderitems;
SELECT * FROM orderitems;
ROLLBACK;
SELECT * from orderitems;
在事务处理块中,提交不会隐含地进行。为进行明确的提交,使用COMMIT语句
为了创建保留点,可如下使用SAVEPOINT语句
延迟提交,SET autocommit=0;
问题16:改善性能
- 一般来说,关键的生产DBMS应该运行在自己的专用服务器上。
- MySQL是用一系列的默认设置预先配置的,从这些设置开始通常是很好的。但过一段时间后你可能需要调整内存分配、缓冲区大小等。为查看当前设置,可使用 SHOW VARIABLES; 和 SHOW STATUS;
- MySQL一个多用户多线程的DBMS,换言之,它经常同时执行多个任务。如果这些任务中的某一个执行缓慢,则所有请求都会执行缓慢。如果你遇到显著的性能不良,可使用 SHOW PROCESSLIST显示所有活动进程(以及它们的线程ID和执行时间)。你还可以用KILL 命令终结某个特定的进程(使用这个命令需要作为管理员登录)。
- 总是有不止一种方法编写同一条 SELECT 语句。应该试验联结、并、子查询等,找出最佳的方法。
- 使用 EXPLAIN 语句让MySQL解释它将如何执行一条 SELECT 语句。
- 一般来说,存储过程执行得比一条一条地执行其中的各条MySQL语句快。
- 决不要检索比需求还要多的数据。换言之,不要用 SELECT * (除非你真正需要每个列)。
- 有的操作(包括 INSERT )支持一个可选的 DELAYED 关键字,如果使用它,将把控制立即返回给调用程序,并且一旦有可能就实际执行该操作。
- 在导入数据时,应该关闭自动提交。你可能还想删除索引(包括FULLTEXT 索引),然后在导入完成后再重建它们。
- 必须索引数据库表以改善数据检索的性能。确定索引什么不是一件微不足道的任务,需要分析使用的 SELECT 语句以找出重复的WHERE 和 ORDER BY 子句。如果一个简单的 WHERE 子句返回结果所花 的时间太长,则可以断定其中使用的列(或几个列)就是需要索引的对象。
- 你的 SELECT 语句中有一系列复杂的 OR 条件吗?通过使用多条SELECT 语句和连接它们的 UNION 语句,你能看到极大的性能改进。
- 索引改善数据检索的性能,但损害数据插入、删除和更新的性能。如果你有一些表,它们收集数据且不经常被搜索,则在有必要之前不要索引它们。(索引可根据需要添加和删除。)
- LIKE 很慢。一般来说,最好是使用 FULLTEXT 而不是 LIKE 。
- 数据库是不断变化的实体。一组优化良好的表一会儿后可能就面目全非了。由于表的使用和内容的更改,理想的优化和配置也会改变。
- 最重要的规则就是,每条规则在某些条件下都会被打破。
问题17:常见命令总结
ALTER TABLE用来更新已存在表的模式。
COMMIT 用来将事务处理写到数据库。
CREATE INDEX用于在一个或多个列上创建索引。
CREATE PROCEDURE创建存储过程
CREATE TABLE 创建表
CREATE USER创建用户账户
CREATE VIEW创建新视图
DELETE删除一行或者多行
DROP 永久地删除数据库对象(表、视图、索引等)
INSERT 给表增加一行
INSERT SELECT插入 SELECT 的结果到一个表
ROLLBACK 用于撤销一个事务处理块
SAVEPOINT 为使用 ROLLBACK 语句设立保留点。
SELECT 用于从一个或多个表(视图)中检索数据
START TRANSACTION 表示一个新的事务处理块的开始。
UPDATE 更新表中一行或多行