二、检索语句 SELECT、ORDER BY、WHERE
介绍如何使用SELECT语句从表中检索一个或多个数据列
第二章: SELECT语句
SQL语句可以在一行给出,也可以分成许多行,分成多行更容易调试。
多条SQL语句必须以分号 分隔。多数DBMS不需要在单条SQL语句后加分号。但特定的DBMS可能必须在单条SQL语句后加上分号。
SQL语句不区分大小写,有些标识符默认是区分大小写的,如数据库名、表名、列名等。
在处理SQL语句时,其中所有空格都被忽略。SQL语句可以在一行上给出,也可以分成许多行。
举例:kedou_jifen.jf_adjust
2.1 检索单个列:
SELECT member_name FROM jf_adjust; ---》从 jf_adjus 表中检索 名为 member_name 的列
返回表中所有行,数据没有过滤,也没有排序,因为没有明确排序查询结果。
2.2 检索多个列:
从一个表中检索多个列,使用相同的SELECT语句。唯一的不同是必须在SELECT关键字后给出多个列名,列名之间必须以逗号分隔。
在选择多个列时,一定要在列名之间加上逗号,最后一个列名后不加,最后一个列名后加上了逗号,将出现错误。
SELECT member_id,member_name,type
FROM jf_adjust;
SQL语句一般返回原始的,无格式的数据。数据的格式化是一个表示问题,而不是一个检索问题。
因此"表示"一般在显示该数据的应用程序中规定。
一般很少使用实际检索出的数据(没有应用程序提供的格式)
2.3 检索所有列
除了指定所需的列外(如上所述,一个或多个列),SELECT语句还可以检索所有的列而不必逐个列出它们。
可以通过在实际列名的位置使用星号(*)通配符来达到。
SELECT * FROM jf_adjust;
给定一个通配符则返回表中所有列。列的顺序一般是列在表定义中出现的物理顺序。
SQL数据很少这样(通常,数据返回给一个根据需要进行格式化或表示的应用程序)
2.4 检索不同的行
SELECT vend_id FROM products;
检索出 products 表中产品的所有供应商ID
2.5 用 DISTINCT 关键字检索出不同值得列表
SELECT DISTINCT vend_id FROM products;
只返回不同(唯一)的vend_id行,使用 DISTINCT 关键字,必须直接放在列名的前面
2.6 限制结果 LIMIT
SELECT prod_name FROM products LIMIT 5 ;
检索 prod_name列,不多于5行
SELECT prod_name FROM products LIMIT 5,5 ;
检索出下一个 5 行,指定开始行和行数;返回从行5开始的5行;带一个值的 LIMIT 总是从第一行开始,给出的数为返回的行数
行0 ,检索出来的第一行为行0而不是行1。 LIMIT 1,1检索出的是第二行而不是第一行。
第三章:排序检索数据
介绍如何使用SELECT语句的ORDER BY子句,根据需要排序检索出的数据。
3.1 排序数据
SELECT member_id
FROM jf_adjust;
这条SQL语句检索返回某个数据库表的单个列,输出没有特定的顺序。
检索出的数据并不是以纯粹的随机方式显示的。如果不排序数据一般将以它在底层表中出现的顺序显示。
这可以是数据最初添加到表中的顺序。但是,如果数据后来进行过更新或删除,则此顺序将会受到DBMS重用回收存储空间的影响。
因此,如果不明确控制的话,不能(也不应该)依赖该排序顺序。
关系数据库设计理论认为,如果不明确规定排序顺序,则不应该假定检索出的数据顺序有意义。
子句:SQL语句由子句构成,有些子句是必须的,而有的可选。一个子句通常由一个关键字加上所提供的数据组成。
例如:SELECT 语句的FROM子句
为了明确的排序用SELECT语句检索出的数据,可使用ORDER BY子句
ORDER BY子句取一个或多个列的名字,据此对输出进行排序。
SELECT member_name FROM jf_adjust ORDER BY member_name;
这条语句除了指示DBMS软件对 member_name 列以字母顺序排序数据的 ORDER BY 子句外,与前面的语句相同。
ORDER BY子句的位置:在指定一条ORDER BY 子句时,应保证它是SELECT语句中最后一条子句。该子句的次序不对将会出现错误消息。
通过非选择列进行排序 :通常 ORDER BY 子句中使用的列将是为显示所选择的列,但是,实际上并不一定要这样,用非检索的列排序数据是完全合法的e
3.2 按多个列排序
经常需要按不止一个列进行数据排序。
例如,如果要显示雇员清单,可能希望按姓和名排序(首先按姓排序,然后在每个姓中再按名排序)。
如果多个雇员具有相同的姓,这样做很有用。
为了按多个列排序,简单指定列名,列名之间用逗号分开即可(就像选择多个列时所做的那样)
SELECT order_no,member_name,expend_date FROM expend_goods ORDER BY member_name, expend_date;
此行代码检索三个列,并按其中两个列对结果进行排序------首先按会员名称,然后再按消费日期排序。
重要的是理解在按多个列排序时,排序的顺序完全按所规定的进行。
对于上述例子中的输出,仅在多个行都是一个会员名时才对订单按expend_date消耗日期进行排序。
如果 member_name 列中所有的值都是唯一的,则不会按 expend_date 排序。
3.3 按列位置排序
除了能用列名指定排序顺序外,ORDER BY还支持按相对列位置进行排序。
SELECT order_no,member_name,expend_date FROM expend_goods ORDER BY 2, 3;
这行代码的输出与上面的查询相同。不同在于ORDER BY子句。SELECT清单中指定的是选择列的相对位置而不是列名。
ORDER BY 2表示按SELECT清单中SELECT order_no,member_name,expend_date第二个列member_name 进行排序。
ORDER BY 2, 3 表示先按 member_name,再按 expend_date 进行排序。
此技术的主要好处在于不用重新输入列名。缺点是:
首先不明确给出列名增加了错用列名排序的可能性。
其次,在对SELECT清单进行更改时容易错误地对数据进行排序
最后,如果进行排序的列不在SELECT清单中,显然不能使用这项技术
3.4 指定排序方向
数据排序不限于升序排序(从A到Z)。这只是默认的排序顺序,还可以使用 ORDER BY子句以降序(从Z到A)顺序排序。
为了进行降序排序,必须指定DESC关键字。
SELECT order_no,member_name,expend_date FROM expend_goods ORDER BY expend_date DESC;
此SQL语句按照消耗日期降序排序
多列降序排序:
SELECT order_no,member_name,expend_date FROM expend_goods ORDER BY expend_date DESC,member_name;
DESC关键字只应用到直接位于其前面的列名。只对 expend_date 列以降序排序,而member_name列(在相同的日期内)仍然按标准的升序排序
在多个列上降序排序:如果想在多个列上进行降序排序,必须对每个列指定DESC关键字。
DESC 为 DESCENDING 的缩写,这两个关键字都可以使用。
DESC的反面是ASC(或ASCENDING),在升序排序时可以指定它。但实际上,ASC没有多大用处,因为升序是默认的
区分大小写和排序顺序:
在字典排序顺序中,A被视为与a相同,这是大多数数据库管理系统的默认行为。
但是许多DBMS允许数据库管理员在需要时改变这种行为(如果你的数据库包含大量外语字符,可能必须这样做)
如果确实急需要改变这种排序顺序,用简单的ORDER BY子句做不到。必须请求数据库管理员帮助。
切记:ORDER BY 子句必须是SELECT语句中的最后一条子句。
第四章:过滤数据
介绍如何使用SELECT语句中WHERE子句指定搜索条件
4.1 使用WHERE子句
只检索所需数据需要制定搜索条件,搜索条件也称为过滤条件。
在SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤。WHERE子句在表名(FROM子句)之后给出。
SELECT order_no,member_name,expend_date FROM expend_goods WHERE member_name='lvyuping';
SQL过滤与应用过滤:数据也可以在应用层过滤。SQL的SELECT语句为客户机应用检索出超过实际所需的数据,然后客户机代码对返回数据进行循环,
以提取出需要的行。这种实现让客户机应用处理数据库的工作将会极大地影响应用的性能,并且使所创建的应用完全不具备可伸缩性。
此外,如果在客户机上过滤数据,服务器不得不通过网络发送多余的数据,这将导致网络带宽的浪费。
在同时使用ORDER BY 和 WHERE 子句时,应该让ORDER BY位于 WHERE之后,否则将会产生错误。
4.2 WHERE子句操作符
SQL的WHERE子句中支持下列列出的所有条件操作符:
检查单个值:
SELECT order_no,member_name,expend_date FROM expend_goods WHERE expend_date> 2017-10-27;
列出订单日期大于'2017-10-27 10:36:26的所有订单
不匹配检查:
SELECT order_no,member_name,expend_date FROM expend_goods WHERE member_name!='kedou';
SELECT order_no,member_name,expend_date FROM expend_goods WHERE member_name<>'kedou';
列出订单会员名部位“kedou”的所有订单
单引号:单引号用来限定字符串,如果是数值不用引号
范围值检查:
检索某个范围的值可以用 BETWEEN 操作符。
SELECT order_no,member_name,expend_date FROM expend_goods WHERE expend_date BETWEEN '2016-07-18 19:20:23' AND '2016-07-19 10:45:36';
检索SQL语句汇总该时间段内的所有订单
空值检查:
在创建表时,表设计人员可以指定其中的列是否可以不包含值。在一个列不包含值时,称其为包含空值NULL
NULL:无值,与字段包含0、空字符串或仅仅包含空格不同
WHERE 子句的 IS NULL 子句可以用来检查具有NULL值的列
SELECT order_no,member_name,success_date FROM expend_goods WHERE success_date IS NULL;
检索出 success_date IS NULL 字段为空的列
第五章:高级数据过滤
介绍如何组合WHERE子句以建立功能更强更高级的搜索条件,学习如何使用NOT和IN操作符
5.1 组合WHERE子句
为了进行更强的过滤,SQL允许给出多个WHERE子句。这些子句以两种方式使用,以AND子句的方式和OR子句的方式使用。
操作符:用来联结或改变WHERE子句中的子句的关键字。也称为逻辑操作符
5.1.1 AND操作符:
为了通过不止一个列进行过滤,可使用AND操作符给WHERE子句附加条件
SELECT order_no,member_name,expend_date FROM expend_goods WHERE member_name='kedou' AND expend_date='2016-07-16 17:14:25';
5.1.2 OR操作符:
WHERE子句中使用的关键字,用来表示检索匹配任一给定条件的行。
许多DBMS在OR WHERE 子句的第一个条件满足的情况下,不在计算第二个条件(在第一个条件满足时,不管第二个条件是否满足,相应的行都将被检索出来)
SELECT member_name,goods_name,success_date FROM expend_goods WHERE member_name='kedou' OR goods_name='实物类积分+金额';
第一个条件满足时,不管第二个条件是否满足,相应的行都将被检索出来
5.1.3 计算次序:
WHERE子句可包含任意数目的AND和OR操作符。允许两者结合以进行复杂和高级的过滤。
SQL在处理OR操作符前,优先处理AND操作符。由于AND在计算次序中优先级更高,操作符被错误的组合。
要以圆括号明确地分组相应的操作符
任何时候使用具有AND和OR操作符的WHERE子句,都应该使用圆括号明确地分组操作符。
5.2 IN操作符
IN---》WHERE子句中用来指定要匹配值的清单的关键字,功能与OR相当
IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN取合法值的由逗号分隔的清单,全都扩在圆括号中。
SELECT activity_id,activity_name,member_name FROM user_activity WHERE member_name IN ('lvyuping','lvyupinglxx')ORDER BY activity_id;
IN操作符与OR操作符完成的功能相同,使用IN操作符的优点:
在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
在使用IN时,计算的次序更容易管理(因为使用的操作符更少)。
IN操作符一般比OR操作符清单执行更快。
IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。
5.3 NOT操作符
NOT--》WHERE子句中用来否定后跟条件的关键字
SELECT activity_id,activity_name,member_name FROM user_activity WHERE NOT member_name IN ('lvyuping','lvyupinglxx')ORDER BY activity_id;
列出除了lvyuping','lvyupinglxx 两个用户外的所有用户活动的活动id,活动名称,用户名称,并按照活动id进行排序
MYSQL不支持这种NOT的格式,在MYSQL中,NOT只用来否定EXISTS(如 NOT EXISTS)
第六章 用通配符进行过滤
本章介绍什么是通配符、如何使用通配符以及怎样使用LIKE操作符进行通配搜索,以便对数据进行复杂过滤
6.1 LIKE操作符
利用通配符可创建比较特定数据的搜索模式。
通配符:用来匹配值的一部分的特殊字符
搜索模式:由字面值、通配符或两者组合构成的搜素条件
通配符本身实际是SQL的WHERE子句中有特殊含义的字符,SQL支持几种通配符。为在搜索子句中使用通配符,必须使用LIKE操作符
LIKE指示DBMS,后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较
谓词:LIKE是谓词而不是操作符。操作符在作为谓词的时候就不是操作符
通配符搜索只能用于文本字段,非文本数据类型字段不能使用统配符搜索
6.1.1 百分号(%)通配符
最常使用的通配符是百分号(%)。在搜索串中,%表示任何字符出现任意次数。
SELECT activity_id,activity_name,member_name FROM user_activity WHERE member_name LIKE 'lv%';
检索任意lv起头的用户名
区分大小写:根据DBMS的不同及其配置,搜索可以是区分大小写的。
通配符可在搜索模式中任意位置使用,并且可以使用多个通配符。
SELECT activity_id,activity_name,member_name FROM user_activity WHERE member_name LIKE '%l%';
--》LIKE '%l%'; 表示匹配任何位置包含文本 l 的值,不论之前或之后出现什么字符
6.1.2 下划线(_)通配符
下划线通配符与%一样,但下划线只匹配单个字符而不是多个字符。
SELECT activity_id,activity_name,member_name FROM user_activity WHERE member_name LIKE '___upinglxx';
LIKE '___upinglxx'; 一个下划线_ 匹配一个字符,此处匹配三个字符
6.1.3 方括号【】通配符
方括号【】通配符用来指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符。
注意事项:
不要过分使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
第七章 创建计算字段
7.1 计算字段
存储在表中的数据都不是应用程序锁需要的。我们需要直接从数据库中检索出转换、计算或格式化过得数据;而不是检索出数据,然后再在客户机
应用程序中重新格式化。
这就是计算字段发挥作用的所在了。计算字段并不实际存在于数据库表中。计算字段是运行时在SELECT语句内创建的。
客户机与服务器的格式 :可在SQL语句内完成的许多转换和格式化工作都可以直接在客户机应用程序内按成。但一般来说,在数据库服务器上完成这些操作比在客户机中
完成要快得多,因为DBMS是设计来快速有效地完成这种处理的。
7.2 拼接字段