《MYSQL必知必会》读书笔记3

HTML5的学习:

http://t.csdn.cn/GZQ5I

组合查询

组合查询是执行多个查询语句(SELECT语句),并将结果作为单个查询结果集返回,这些组合查询通常称为并或符合查询。

创建组合查询

可用UNION操作来组合数条SQL查询,利用UNION,可给出多条SELECT语句,它们的结果组合成单个结果集。

使用UNION

给出每条SELECT语句,在各条语句之间放上关键字UNION。

加入需要价格小于等于5的所有物品的一个列表,而且还想包括供应商1001,和1002生产的所有物品(不考虑价格)。可以用WHERE子句来完成,也可以使用UNION。

SELECT vend_id,prod_id,prod_price FROM products prod_price<=5;

检索价格不高于5的所有物品

SELECT vend_id,prod_id,prod_price FROM products WHERE vend_id IN(1001,1002);

使用IN找出供应商1001和1002生成的所有物品。

 

组合上面两条语句:

SELECT vend_id,prod_id,prid_price

FROM produces

WHERE prod_price<=5

UNION

SELECT vend_id,prod_id,prod_price

FROM produces

WHERE vend_id IN(1001,1002);

语句用UNION关键字分隔,UNION指示MYSWL执行两条SELECT语句,并且把输出组成的那个查询结果集。

UNION规则

  • UNION必须有两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合四条SELECT语句,将要使用三个UNION关键字)
  • UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)
  • 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含地转换的类型(例如,不同数值类型或不同日期类型)

包含或取消重复的行

UNION从查询结果集中自动去除了重复的行(它的行为与单条SELECT语句中使用多个WHERE子句一样),这是UNION的默认行为,但是也可以改变:

SELECT vend_id,prod_id,prod_price

FROM produces

WHERE prod_price<=5 

UNION ALL

SELECT vend_id,prod_id,prod_price

FROM products

WHERE vend_id IN (1002,1002);

这个语句不会取消重复的行。

UNION和WHERE:

UNION几乎总是完成与多个WHERE条件相同的工作,UNION ALL是UNION的一种表现形式,它完成WHERE子句完成不了的工作,如果确实需要每个条件的匹配行全部出现(包括重复行),则必须使用UNION ALL而不是WHERE。

对组合查询结果集排序

SELECT语句的出错用ORDER BY子句排序,在用UNION组合查询时,只能用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后,对于结果集,不存在用一种方式排序一部分,而是用另一种方式,排序另一部分的情况,因此不允许使用多条ORDER BY子句。

使用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)

ORDER BY vend_id,prod_price;

这条UNION在最后一条语句后使用了ORDER BY子句,虽然ORDER BY子句似乎是最后一条SELECT语句的组成部分,但实际上MYSQL将用它来排序所有的SELECT语句返回的所有结果。

全文本搜索

MYSQL支持几种基本的数据库引擎,并非所有的引擎都支持全文本搜索。

两个最常使用的引擎为MYISAM和InnoDB,MYISAM正常全文本搜索,InnoDB不支持。

LIKE关键字,可以利用通配符匹配文本(和部分文本)。使用LIKE关键字,可以查找包含特殊值或部分值的行(不管这些值位于列内什么位置)

使用正则表达式,可以编写操作所需行的非常复杂的匹配模式

虽然这些搜索机制非常有用,但有几个限制:

  • 性能——通配符和正则表达式匹配通常要求MYSQL查实匹配表中所有的行(而且这些搜索极少使用表索引),因此由于被搜索的行数不断增加,这些搜索很耗时
  • 明确控制——使用通配符和正则表达式匹配,很难(而且并不总是能)明确地匹配什么和不匹配什么。(例如:指定一个词必须匹配,一个词必须不匹配,而一个词仅在第一个词确实匹配的情况下才可以匹配或者才可以不匹配)
  • 智能化结果——虽然基于通配符和正则表达式的搜索提供了非常灵活的搜索,但他们都不能提供选择结果的方法,一个特殊词的搜索将会返回包含该词的所有行,二部区分包含单个匹配的行包含多个匹配的行(按照可能是更好的匹配来排列他们),类似,一个特殊词的搜索将保护找出不包含该词但包含其他相关词的行。

使用全文本搜索

wield进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表列进行适当设计后,MYSQL会自动进行所有的索引和重新索引,在索引之后,SELECT可以与Match()和Against()一起使用执行搜索。

启用全文本搜索支持

一般在创建表时启用全文本搜索,CREATE TABLE语句吉首FULLTEXT子句,它给出呗索引的一个逗号分隔的列表。

CREATE TABLE productnotes

(

        node_id        int        NOT NULL AUTO_INCREMENT,

        prod_id        char(10)        NOT NULL,

        note_date datetime        NOT NULL,

        note_text        text        NULL,

        PRIMSRY KEY(note_id),

        FULLTEXT(note_text)

)ENGINE=MyISAM;

CREATE TABLE语句定义表productnotes并列出它所包含的列即可,这些列中有一个名为note_text的列,为了进行全文本搜索,MYSQL根据子句FULLTEXT(note_text)的指示对他进行索引,这里的FULLTEXT索引单个列,如果需要也可以指定多个列。

在定义之后,MYSQL自动维护该索引,在增加、更新或删除行时,索引随之自动更新。

可以在创建表时指定FULLTEXT,或者在稍后指定(在这种情况下,所有的已有数据必须立即索引)。

不要在导入数据时使用FULLTEXT,更新索引要花时间,如果正在导入数据到一个新表,此时不同构启用FULLTEXT索引,应该首先导入所有数据,然后再修改表。

进行全文本搜索

在索引之后,使用两个函数Match()和Against()指定要使用的搜索表达式。

SELECT node_text FROM productnotes WHERE Match(note_text)Against('rabbit');

在SELECT语句检索单个列note_text,由于WHERE子句,一个全文本搜索被执行,Match(note_text)指示MYSQL针对指定的两行包含词rabbit,这两个行被返回。

传递给Match()的值必须与FULLTEXT()定义中的相同,如果指定多个列,则必须列出他们(而且次序正确)

搜索不区分大小写,除非使用BINARY方式。

SELECT note_text FROM productnotes WHERE note_text LIKE '%rabbit%';

这条SELECT语句同样检索出两行,但次序不同(虽然不总是出现这种情况)

SELECT note_text,Match(note_text)Against('rabbit')AS rank FROM productnotes;

在SELECT而不是WHERE子句中使用Match()和Against()。使所有行都被返回(因为没有WHERE子句)Match()和Against()用来建立一个计算列(别名为rank)

不包含次rabbit的行等级为0,确实包含次rabbit的两个行每行都有一个等级值,文本中词靠前的行的等级制比词靠后的行的等级值高。

使用查询扩展

查询扩展用来设法放宽所返回的全文本搜索结果的范围,考虑下面的情况:想找到所有提到anvils的注释包含词anvils,但你还想找出你的搜索有关的所有其他行,即使他们不包含词anvils。

SELECT note_text 

FROM productnotes

WHERE Match(note_text) Against ('anvils');

因此只返回包含词anvils的行

SELECT note_text FROM productnotes WHERE Match(note_text)Against('anvils' WITH QUERY EXPANSION);

查询扩展极大地增加了返回的行数,但这样做也增加了实际上并不想要的行的数目。

布尔文本搜索

MYSQL支持全文本搜索的另一种方式是布尔方式。

需要提供:

  • 要匹配的词
  • 要排斥的词(如果某行包含这个词,则不返回改行,即使它包含其他指定的词也是如此);
  • 排列提示(指定某些词比其他词更重要,更重要的词等级更高)
  • 表达式分组
  • 另外一些内容

即使没有FULLTEXT索引也可以使用布尔文本搜索。

SELECT note_text

FROM productnotes

WHERE Match(note_text) Against('heavy' IN BOOLESN MODE);

全文本搜索检索包含词heavy的所有行(有两行),其中使用了关键字IN BOOLEAN MODE,实际上没有指定布尔操作符。

IN BOOLEAN MODE的行为差异:虽然这个例子的结果与没有IN BOOLEAN MODE的相同,但其行为有一个重要的差别。

SELECT note_text

FROM priductnotes

WHERE Match(note_text)Against('heacy -rope*' IN BOOLEAN MODE);

匹配词heavy,但-rope*明确的只是MYSQL排除包含rope*(任何以rope开始的词,包括ropes)的行

注意:

  • 许多词出现的频率很高,搜索它们没有用处(返回太多的结果)。MySQL规定如果一个词出现在50%以上 的行中,则将它作为一个非用词忽略。50%规则不用于IN BOOLEAN MODE
  • 在索引全文本数据时,短词被忽略且从索引中排除。短词定义为 那些具有3个或3个以下字符的词(如果需要,这个数目可以更改)。
  • 如果表中的行数少于3行,则全文本搜索不返回结果(因为每个词 或者不出现,或者至少出现在50%的行中)。
  • 忽略词中的单引号。例如,don't索引为dont。
  • 不具有词分隔符(包括日语和汉语)的语言不能恰当地返回全文 本搜索结果。

插入数据

  • 插入完整的行
  • 插入行的一部分
  • 插入多行
  • 插入某些查询的结果

插入完整的行

INSERT语句一般不会产生输出

INSERT INTO Cusstomers VALUES(NULL,'Pep E. LaPew','100 Main Street',Los Angeles','CA','90046','USA',NULL,NULL);

INSERT INTO customers

(cust_name,cust_address,cust_state,cust_zip,cust_country,cust_contact,cust_email) VALUES('Pep E. LaPew','100 Main Street',Los Angeles','CA','90046','USA',NULL,NULL);

可以变换顺序。

  • 总是使用列的列表,即使表结构发生了变化,也可以使SQL代码继续发挥作用
  • 可以使用多条INSERT语句插入多行每条语句用一个分号结束

插入检索出的数据

使用INSERT SELECT从custnew中将搜友数据导入customers。SELECT语句从custnew检索出要插入的值,而不是列出他们。

SELECT中列出的每个列对应与customers表名中有多少行。

如果这个表为空,则没有行被插入,也不会产生错误,如果这个表中有数据,则多有数据都会被插入到customers中。

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 custnew;

更新和删除数据

更新数据

  • 更新表中特定行
  • 更新表中所有行

不要省略WHERE子句:稍不注意就会更新表中的所有行。

  • 要更新的表
  • 列名和他们的新值
  • 确定要更新行的过滤条件

UPDATE customers SET cust_email='[email protected]' WHERE cust_id=10005;

要更新的表名是customwes,SET命令用来将新值赋给被更新的列

WHERE子句是告诉MYSQL更新哪一行,没有WHERE子句,酱爆包这个电子邮箱地址更新customers表中的所有行。

可以在UPDATE语句中使用子查询。

IGNORE关键字:提供UPDATE更新多行,并且在更新这些行中的一行或多行时出现一个错误,整个UPDATE操作被取消。但是使用IGNORE关键字,即使发生错误,也继续更新。

删除某个列的值:

UPDATE customers SET cust_email=NULL WHERE cust_id=10005;

删除数据

  • 从一个表中删除特定的行
  • 从表中删除所有行

不要省略WHERE子句:因为稍不注意,就会错误地删除表中所有行。

DELETE FROM customers WHERE cust_id=10006;

从customers表中删除客户10006,如果省略WHERE语句,将会删除表中每个客户。

删除的是表的内容,而不是表

更快的删除:如果从表中删除所有行,不要使用DELETE,可使用TRUNCATE TABLE语句,完成相同的工作,但是速度更快。

创建和操作表

创建表

  • 新表的名字,在关键字CREATE TABLE之后给出
  • 表列的名字和定义,用逗号分隔

CREATE TABLE orders(

order_num        int        NOT NULL AUTO_INCREMENT,

order_date        datetime        NOT NULL,

cust_id        int        NOT NULL,

PRIMARY        KEY(order_num)

)ENGINE=InnoDB;

关键字NOT NULL:如果插入没有值的列,这将会阻止插入没有值的列。如果 试图插入没有值的列,将返回错误,且插入失败。

NULL值与空串不一样。NULL值是没有值, 它不是空串。如果指定 ' '(两个单引号,其间没有字符),这 在NOT NULL列中是允许的。空串是一个有效的值,它不是无值。NULL值用关键字NULL而不是空串指定。

主键

主键值必须唯一,表中的每个行必须唯一的主键值。

也可以创建由多个列组成的主键值

CREATE TABLE orderitems(

order_num        int        NOT NULL,

order_item        int        NOT NULL,

cust_id        char(10)        NOT NULL,

quantity        int        NOT NULL,

item_price decimal(order_num,order_item)

PRIMARY KEY (order_num,order_item)

)ENGINE=InnoDB;

使用订单号(order_num列)和订单物品(order_item列)的组合作为主键。

主键为唯一标识表的每个行和列,主键只能使用不允许NULL值的列,允许NULL的值的列不能作为唯一标识。

使用AUTO_INCREMENT

列每当增加一行时自动增量。每次 执行一个INSERT操作时,MySQL自动对该列增量

每个表只允许一个AUTO_INCREMENT列,而且它必须被索引(如,通 过使它成为主键)。

cust_id        int        NOT NULL AUTO_INCREMENT

指定默认值

在插入时没有给出值,此时允许使用默认值

quantity        int        NOT NULL DEFAULT 1

指定默认值为1

指定默认值不是使用函数,只支持常量

引擎类型

使用的CREATE TABLE 表语句全都已ENGINE=InnoDB语句结束。

不同引擎各自有不同的功能和特性,为不同任务选择之前的引擎来获得良好的灵活性。

  • InnoDB是一个可靠的事务处理引擎,包装成全文本搜索
  • MEMORY在功能上等同于MyISAM,但由于数据存储在内存,而不是磁盘中,所以速度很快
  • MyISAM是一个性能极高的引擎,支持全文本搜索,但不支持事务处理

更新表

在ALTER TABLE更改表结构,要给出下面信息:

  • 在ALTER TABLE之后给出要更改的表名,该表必须存在,否则将出错
  • 所更改的列表

ALTER TABLE vendors

ADD vend_phone CHAR(20);

给表vendors增加一个名为vend_phone的列,必须明确其数据类型。

ALTER TABLE vendors 

DROP COLUMN vend_phone;

删除刚刚新增的列

ALTER TABLE还有一个用途是定义外键:

ALTER TABLE orderitems

ADD CONSTRAINT fk_orderitems_orders

FOREIGN KEY(order_num) REFEITEMS orders (order_num);

删除表

DROP TABLE customers;

删除整个表,而不是其内容

重命名表

RENAME TABLE customers2 TO customers;

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(总结,数据库MQSQL,sql,数据库)