第1课 了解SQL
1.1 数据库基础
1.1.1 数据库
数据库是一个以某种有组织的方式存储的数据集合。
数据库(database)
保存有组织的数据的容器(通常是一个文件或一组文件)。
注意:误用导致混淆
数据库软件应称为数据库管理系统(即DBMS)。数据库是通过DBMS创建和操纵的容器,而具体它究竟是什么,形式如何,各种数据库都不一样。
1.1.2 表
表(table)
某种特定类型数据的结构化清单。
数据库中的每个表都有一个名字来标识自己。这个名字是唯一的,即数据库中没有其他表具有相同的名字。
说明:表名
使表名成为唯一的,实际上是数据库名和表名等的组合。有的数据库还使用数据库拥有者的名字作为唯一名的一部分。也就是说,虽然在相同数据库中不能两次使用相同的表名,但在不同的数据库中完全可以使用相同的表名。
表具有一些特性,这些特性定义了数据在表中如何存储,包含存储什么样的数据,数据如何分解,各部分信息如何命名等信息。描述表的这组信息就是所谓的模式(schema),模式可以用来描述数据库中特定的表,也可以用来描述整个数据库(和其中表的关系)。
模式
关于数据库和表的布局及特性的信息。
1.1.3 列和数据类型
列(column)
表中的一个字段。所有表都是由一个或多个列组成的。
提示:分解数据
正确地将数据分解为多个列极为重要。例如,城市、州、邮政编码应该总是彼此独立的列。通过分解这些数据,才有可能利用特定的列对数据进行分类和过滤(如找出特定州或特定城市的所有顾客)。如果城市和州组合在一个列中,则按州进行分类或过滤就会很困难。
数据库中每个列都有相应的数据类型。数据类型(datatype)定义了列可以存储哪些数据种类。
数据类型
所允许的数据的类型。每个表列都有相应的数据类型,它限制(或允许)该列中存储的数据。
1.1.4 行
表中的数据是按行存储的,所保存的每个记录存储在自己的行内。如果将表想象为网格,网格中垂直的列为表列,水平行为表行。
行(row)
表中的一个记录。
1.1.5 主键
主键(primary key)
一列(或一组列),其值能够唯一标识表中每一行。
提示:应该总是定义主键
虽然并不总是需要主键,但多数数据库设计者都会保证他们创建的每个表具有一个主键,以便于以后的数据操作和管理。
表中的任何列都可以作为主键,只要它满足以下条件:
- 任意两行都不具有相同的主键值;
- 每一行都必须具有一个主键值(主键列不允许NULL值);
- 主键列中的值不允许修改或更新;
- 主键值不能重用(如果某行从表中删除,它的主键不能赋给以后的新行)。
主键通常定义在表的一列上,但并不是必需这么做,也可以一起使用多个列作为主键。在使用多列作为主键时,上述条件必须应用到所有列,所有列值的组合必须是唯一的(但单个列的值可以不唯一)。
1.2 什么是SQL
SQL(发音为字母S-Q-L或sequel)是结构化查询语言(Structured Query Language)的缩写。
SQL有如下的优点。
- SQL不是某个特定数据库供应商专有的语言。几乎所有重要的DBMS都支持SQL,所以学习此语言使你几乎能与所有数据库打交道。
- SQL简单易学。它的语句全都是由有很强描述性的英语单词组成,而且这些单词的数目不多。
- SQL虽然看上去很简单,但实际上是一种强有力的语言,灵活使用其语言元素,可以进行非常复杂和高级的数据库操作。
第2课 检索数据
2.1 SELECT语句
SQL语句是由简单的英语单词构成的。这些单词称为关键字,每个SQL语句都是由一个或多个关键字构成的。
SELECT
语句的用途是从一个或多个表中检索信息。
关键字(keyword)
作为SQL组成部分的保留字。关键字不能用作表或列的名字。
为了使用SELECT
检索表数据,必须至少给出两条信息——想选择什么,以及从什么地方选择。
2.2 检索单个列
SELECT prod_name
FROM Products;
提示:结束SQL语句
多条SQL语句必须以分号(;
)分隔。
提示:SQL语句和大小写
请注意,SQL语句不区分大小写,因此SELECT与select是相同的。
提示:使用空格
在处理SQL语句时,其中所有空格都被忽略。SQL语句可以写成长长的一行,也可以分写在多行。
2.3 检索多个列
要想从一个表中检索多个列,仍然使用相同的SELECT
语句。唯一的不同是必须在SELECT
关键字后给出多个列名,列名之间必须以逗号分隔。
提示:当心逗号
在选择多个列时,一定要在列名之间加上逗号,但最后一个列名后不加。如果在最后一个列名后加了逗号,将出现错误。
SELECT prod_id, prod_name, prod_price
FROM Products;
2.4 检索所有列
除了指定所需的列外,SELECT语句还可以检索所有的列而不必逐个列出它们。在实际列名的位置使用星号(*)通配符可以做到这点,如下所示。
SELECT *
FROM Products;
警告:使用通配符
一般而言,除非你确实需要表中的每一列,否则最好别使用*
通配符。虽然使用通配符能让你自己省事,不用明确列出所需列,但检索不需要的列通常会降低检索和应用程序的性能。
2.5 检索不同的值
使用DISTINCT
关键字,指示数据库只返回不同的值
SELECT DISTINCT vend_id
FROM Products;
警告:不能部分使用
DISTINCT
DISTINCT
关键字作用于所有的列,不仅仅是跟在其后的那一列。例如,你指定SELECT DISTINCT vend_id, prod_price
,除非指定的两列完全相同,否则所有的行都会被检索出来。
2.6 限制结果
SELECT
语句返回指定表中所有匹配的行,很可能是每一行。如果你只想返回第一行或者一定数量的行,该怎么办呢?这是可行的,然而遗憾的是,各种数据库中的这一SQL实现并不相同。
在SQL Server和Access中使用SELECT
时,可以使用TOP
关键字来限制最多返回多少行,如下所示:
# 使用SELECT TOP 5语句,只检索前5行数据。
SELECT TOP 5 prod_name
FROM Products;
如果你使用的是DB2,很可能习惯使用下面这一DBMS特定的SQL语句,像这样:
SELECT prod_name
FROM Products
FETCH FIRST 5 ROWS ONLY;
如果你使用Oracle,需要基于ROWNUM
(行计数器)来计算行,像这样:
SELECT prod_name
FROM Products
WHERE ROWNUM <=5;
如果你使用MySQL、MariaDB、PostgreSQL或者SQLite,需要使用LIMIT
子句,像这样:
SELECT prod_name
FROM Products
LIMIT 5;
为了得到后面的5行数据,需要指定从哪儿开始以及检索的行数,像这样:
SELECT prod_name
FROM Products
LIMIT 5 OFFSET 5;
LIMIT指定返回的行数。带OFFSET的LIMIT指定从哪儿开始。
警告:第0行
第一个被检索的行是第0行,而不是第1行。因此,LIMIT 1 OFFSET 1会检索第2行,而不是第1行。
提示:MySQL和MariaDB快捷键
MySQL和MariaDB支持简化版的LIMIT 4 OFFSET 3
语句,即LIMIT 3,4
。使用这个语法,,
之前的值对应OFFSET
,,
之后的值对应LIMIT
。
2.7 适用注释
- 添加一些描述性的注释,这便于你自己今后参考,或者供项目后续参与人员参考
- 同样适用于SQL文件开始处的内容,它可能包含程序员的联系方式、程序描述以及一些说明。
- 注释的另一个重要应用是暂时停止要执行的SQL代码。如果你碰到一个长SQL语句,而只想测试它的一部分,那么应该注释掉一些代码,以便MariaDB将其视为注释而加以忽略。
SELECT prod_name -- 这是一条行内注释
FROM Products;
# 这是一条单行注释
SELECT prod_name
FROM Products;
/* SELECT prod_name, vend_id
FROM Products; */
SELECT prod_name
FROM Products;
第3课 排序检索数据
3.1 排序数据
子句(clause)
SQL语句由子句构成,有些子句是必需的,有些则是可选的。一个子句通常由一个关键字加上所提供的数据组成。
为了明确地排序用SELECT
语句检索出的数据,可使用ORDER BY
子句。ORDER BY
子句取一个或多个列的名字,据此对输出进行排序。
SELECT prod_name
FROM Products
ORDER BY prod_name;
ORDER BY
子句的位置
在指定一条ORDER BY
子句时,应该保证它是SELECT
语句中最后一条子句。如果它不是最后的子句,将会出现错误消息。
通过非选择列进行排序
通常,ORDER BY
子句中使用的列将是为显示而选择的列。但是,实际上并不一定要这样,用非检索的列排序数据是完全合法的。
3.2 按多个列排序
要按多个列排序,简单指定列名,列名之间用逗号分开即可(就像选择多个列时那样)。
下面的代码检索3个列,并按其中两个列对结果进行排序——首先按价格,然后按名称排序。
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price, prod_name;
3.3 按列位置排序
除了能用列名指出排序顺序外,ORDER BY
还支持按相对列位置进行排序。
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY 2, 3;
ORDER BY 2
表示按SELECT
清单中的第二个列prod_name
进行排序。ORDER BY 2,3
表示先按prod_price
,再按prod_name
进行排序。
这一技术的主要好处在于不用重新输入列名。但它也有缺点。首先,不明确给出列名有可能造成错用列名排序。其次,在对SELECT清单进行更改时容易错误地对数据进行排序(忘记对ORDER BY子句做相应的改动)。最后,如果进行排序的列不在SELECT清单中,显然不能使用这项技术。
按非选择列排序
显然,当根据不出现在SELECT
清单中的列进行排序时,不能采用这项技术。但是,如果有必要,可以混合匹配使用实际列名和相对列位置。
3.4 指定排序方向
数据排序不限于升序排序(从A到Z),这只是默认的排序顺序。还可以使用ORDER BY
子句进行降序(从Z到A)排序。为了进行降序排序,必须指定DESC
关键字。
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC;
警告:在多个列上降序排序
如果想在多个列上进行降序排序,必须对每一列指定DESC
关键字。
请注意,DESC
是DESCENDING
的缩写,这两个关键字都可以使用。与DESC
相对的是ASC
(或ASCENDING
),在升序排序时可以指定它。但实际上,ASC
没有多大用处,因为升序是默认的(如果既不指定ASC
也不指定DESC
,则假定为ASC
)。
提示:区分大小写和排序顺序
在对文本性数据进行排序时,A与a相同吗?a位于B之前,还是Z之后?这些问题不是理论问题,其答案取决于数据库的设置方式。在字典(dictionary)排序顺序中,A被视为与a相同,这是大多数数据库管理系统的默认行为。但是,许多DBMS允许数据库管理员在需要时改变这种行为(如果你的数据库包含大量外语字符,可能必须这样做)。
这里的关键问题是,如果确实需要改变这种排序顺序,用简单的ORDER BY子句可能做不到。你必须请求数据库管理员的帮助。
第4课 过滤数据
4.1 使用WHERE子句
在SELECT
语句中,数据根据WHERE
子句中指定的搜索条件进行过滤。WHERE
子句在表名(FROM
子句)之后给出,如下所示:
SELECT prod_name, prod_price
FROM Products
WHERE prod_price = 3.49;
提示:SQL过滤与应用过滤
数据也可以在应用层过滤。为此,SQL的SELECT
语句为客户端应用检索出超过实际所需的数据,然后客户端代码对返回数据进行循环,提取出需要的行。通常,这种做法极其不妥。优化数据库后可以更快速有效地对数据进行过滤。而让客户端应用(或开发语言)处理数据库的工作将会极大地影响应用的性能,并且使所创建的应用完全不具备可伸缩性。此外,如果在客户端过滤数据,服务器不得不通过网络发送多余的数据,这将导致网络带宽的浪费。
警告:WHERE子句的位置
在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则将会产生错误。
4.2 WHERE字句操作符
我们在做相等检验时看到了第一个WHERE
子句,它确定一个列是否包含指定的值。
操作符 | 说明 |
---|---|
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
! | 不小于 |
> | 大于 |
>= | 大于等于 |
!> | 不大于 |
BETWEEN | 在指定两个值之间 |
IS NULL | 为NULL值 |
警告: 操作符兼容
表4-1中列出的某些操作符是冗余的(如< >
与!=
相同,!<
相当于>=
)。并非所有DBMS都支持这些操作符
4.2.1 检查单个值
第一个例子是列出所有价格小于10美元的产品:
SELECT prod_name, prod_price FROM Products WHERE prod_price < 10;
4.2.2 不匹配检查
列出所有不是供应商DLL01
制造的产品:
SELECT vend_id, prod_name
FROM Products
WHERE vend_id <> 'DLL01';
提示:何时使用引号
如果仔细观察上述WHERE子句中的条件,会看到有的值括在单引号内,而有的值未括起来。单引号用来限定字符串。如果将值与字符串类型的列进行比较,就需要限定引号。用来与数值列进行比较的值不用引号。
警告:是!=还是<>?
!=和<>通常可以互换。但是,并非所有DBMS都支持这两种不等于操作符。例如,Microsoft Access支持<>而不支持!=。
4.2.3 范围值检查
要检查某个范围的值,可以使用BETWEEN操作符。其语法与其他WHERE子句的操作符稍有不同,因为它需要两个值,即范围的开始值和结束值。
下面的例子说明如何使用BETWEEN
操作符,它检索价格在5美元和10美元之间的所有产品:
SELECT prod_name, prod_price
FROM Products
WHERE prod_price BETWEEN 5 AND 10;
在使用BETWEEN
时,必须指定两个值——所需范围的低端值和高端值。这两个值必须用AND
关键字分隔。BETWEEN
匹配范围中所有的值,包括指定的开始值和结束值。
4.2.4 空值检查
在创建表时,表设计人员可以指定其中的列能否不包含值。在一个列不包含值时,称其包含空值NULL
。
NULL
无值(no value),它与字段包含0、空字符串或仅仅包含空格不同。
确定值是否为NULL
,不能简单地检查是否= NULL
。SELECT
语句有一个特殊的WHERE
子句,可用来检查具有NULL
值的列。这个WHERE
子句就是IS NULL
子句。其语法如下:
SELECT prod_name
FROM Products
WHERE prod_price IS NULL;
警告:NULL和非匹配
通过过滤选择不包含指定值的所有行时,你可能希望返回含NULL值的行。但是这做不到。因为未知(unknown)有特殊的含义,数据库不知道它们是否匹配,所以在进行匹配过滤或非匹配过滤时,不会返回这些结果。过滤数据时,一定要验证被过滤列中含NULL的行确实出现在返回的数据中。
第5课 高级数据过滤
5.1 组合WHERE子句
为了进行更强的过滤控制,SQL允许给出多个WHERE
子句。这些子句有两种使用方式,即以AND
子句或OR
子句的方式使用。
操作符(operator)
用来联结或改变WHERE
子句中的子句的关键字,也称为逻辑操作符(logical operator)。
5.1.1 AND操作符
要通过不止一个列进行过滤,可以使用AND
操作符给WHERE
子句附加条件。下面的代码给出了一个例子:
SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;
AND
用在WHERE
子句中的关键字,用来指示检索满足所有给定条件的行。
这个例子只包含一个AND
子句,因此最多有两个过滤条件。可以增加多个过滤条件,每个条件间都要使用AND
关键字。
5.1.2 OR操作符
OR操作符与AND操作符正好相反,它指示DBMS检索匹配任一条件的行。事实上,许多DBMS在OR WHERE子句的第一个条件得到满足的情况下,就不再计算第二个条件了(在第一个条件满足时,不管第二个条件是否满足,相应的行都将被检索出来)。
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = ‘BRS01’;
OR
WHERE
子句中使用的关键字,用来表示检索匹配任一给定条件的行。
5.1.3 求值顺序
WHERE
子句可以包含任意数目的AND
和OR
操作符。允许两者结合以进行复杂、高级的过滤。
SQL(像多数语言一样)在处理OR操作符前,优先处理AND操作符。
此问题的解决方法是使用圆括号对操作符进行明确分组。请看下面的SELECT
语句及输出:
SELECT prod_name, prod_price
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = ‘BRS01’)
AND prod_price >= 10;
提示:在
WHERE
子句中使用圆括号
任何时候使用具有AND
和OR
操作符的WHERE
子句,都应该使用圆括号明确地分组操作符。不要过分依赖默认求值顺序,即使它确实如你希望的那样。使用圆括号没有什么坏处,它能消除歧义。
5.2 IN操作符
IN
操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN
取一组由逗号分隔、括在圆括号中的合法值。下面的例子说明了这个操作符:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id IN ( 'DLL01', 'BRS01' )
ORDER BY prod_name;
为什么要使用IN操作符?其优点为:
- 在有很多合法选项时,IN操作符的语法更清楚,更直观。
- 在与其他AND和OR操作符组合使用IN时,求值顺序更容易管理。
IN操作符一般比一组OR操作符执行得更快 - IN的最大优点是可以包含其他SELECT语句,能够更动态地建立WHERE子句。
IN
WHERE
子句中用来指定要匹配值的清单的关键字,功能与OR
相当。
5.3 NOT操作符
WHERE子句中的NOT操作符有且只有一个功能,那就是否定其后所跟的任何条件。因为NOT从不单独使用(它总是与其他操作符一起使用),所以它的语法与其他操作符有所不同。NOT关键字可以用在要过滤的列前,而不仅是在其后。
NOT
WHERE
子句中用来否定其后条件的关键字。
为了列出除DLL01
之外的所有供应商制造的产品,可编写如下的代码:
SELECT prod_name
FROM Products
WHERE NOT vend_id = 'DLL01'
ORDER BY prod_name;
为什么使用NOT?对于这里的这种简单的WHERE子句,使用NOT确实没有什么优势。但在更复杂的子句中,NOT是非常有用的。例如,在与IN操作符联合使用时,NOT可以非常简单地找出与条件列表不匹配的行。
说明:MariaDB中的
NOT
MariaDB支持使用NOT
否定IN
、BETWEEN
和EXISTS
子句。大多数DBMS允许使用NOT
否定任何条件。
第6课 用通配符进行过滤
6.1 LIKE操作符
通配符(wildcard)
用来匹配值的一部分的特殊字符。
搜索模式(search pattern)
由字面值、通配符或两者组合构成的搜索条件。
通配符本身实际上是SQL的WHERE子句中有特殊含义的字符,SQL支持几种通配符。为在搜索子句中使用通配符,必须使用LIKE操作符。LIKE指示DBMS,后跟的搜索模式利用通配符匹配而不是简单的相等匹配进行比较。
通配符搜索只能用于文本字段(串),非文本数据类型字段不能使用通配符搜索。
6.1.1 百分号(%)通配符
最常使用的通配符是百分号(%
)。在搜索串中,%
表示任何字符出现任意次数。例如,为了找出所有以词Fish
起头的产品,可发布以下SELECT
语句:
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE 'Fish%';
说明:Access通配符
如果使用的是Microsoft Access,需要使用*
而不是%
。
说明:区分大小写
根据DBMS的不同及其配置,搜索可以是区分大小写的。如果区分大小写,则'fish%'
与Fish bean bag toy
就不匹配。
通配符可在搜索模式中的任意位置使用,并且可以使用多个通配符。下面的例子使用两个通配符,它们位于模式的两端:
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '%bean bag%';
通配符也可以出现在搜索模式的中间,虽然这样做不太有用。下面的例子找出以F
起头、以y
结尾的所有产品:
SELECT prod_name
FROM Products
WHERE prod_name LIKE 'F%y';
提示:根据部分信息搜索电子邮件地址
有一种情况下把通配符放在搜索模式中间是很有用的,就是根据邮件地址的一部分来查找电子邮件,例如WHERE email LIKE b%@forta.com
。
需要特别注意,除了能匹配一个或多个字符外,%
还能匹配0个字符。%
代表搜索模式中给定位置的0个、1个或多个字符。
警告:请注意
NULL
通配符%
看起来像是可以匹配任何东西,但有个例外,这就是NULL
。子句WHERE prod_name LIKE '%'
不会匹配产品名称为NULL
的行。
6.1.2 下划线(_)通配符
另一个有用的通配符是下划线(_
)。下划线的用途与%
一样,但它只匹配单个字符,而不是多个字符。
说明:DB2通配符
DB2不支持通配符_
。说明:Access通配符
如果使用的是Microsoft Access,需要使用?
而不是_
。
与%
能匹配0个字符不同,_
总是刚好匹配一个字符,不能多也不能少。
6.1.3 方括号([])通配符
方括号([]
)通配符用来指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符。
说明:并不总是支持集合
与前面描述的通配符不一样,并不是所有DBMS都支持用来创建集合的[]。只有微软的Access和SQL Server支持集合。为确定你使用的DBMS是否支持集合
此通配符可以用前缀字符^(脱字号)来否定。例如,下面的查询匹配不以J或M起头的任意联系人名:
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[^JM]%'
ORDER BY cust_contact;
说明:Access中的否定集合
如果使用的是Microsoft Access,需要用!
而不是^
来否定一个集合,因此,使用的是[!JM]
而不是[^JM]
。
当然,也可以使用NOT
操作符得出相同的结果。^
的唯一优点是在使用多个WHERE
子句时可以简化语法:
SELECT cust_contact
FROM Customers
WHERE NOT cust_contact LIKE '[JM]%'
ORDER BY cust_contact;
6.2 使用通配符的技巧
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
- 在确实需要使用通配符时,也尽量不要把它们用在搜索模式的开始处。把通配符置于开始处,搜索起来是最慢的。
- 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。
第7课 创建计算字段
7.1 计算字段
计算字段并不实际存在于数据库表中。计算字段是运行时在SELECT
语句内创建的。
字段(field)
基本上与列(column)的意思相同,经常互换使用,不过数据库列一般称为列,而术语字段通常与计算字段一起使用。
需要特别注意,只有数据库知道SELECT语句中哪些列是实际的表列,哪些列是计算字段。从客户端(如应用程序)来看,计算字段的数据与其他列的数据的返回方式相同。
提示:客户端与服务器的格式
在SQL语句内可完成的许多转换和格式化工作都可以直接在客户端应用程序内完成。但一般来说,在数据库服务器上完成这些操作比在客户端中完成要快得多。
7.2 拼接字段
拼接(concatenate)
将值联结到一起(将一个值附加到另一个值)构成单个值。
在SQL中的SELECT语句中,可使用一个特殊的操作符来拼接两个列。根据你所使用的DBMS,此操作符可用加号(+)或两个竖杠(||)表示。在MySQL和MariaDB中,必须使用特殊的函数。
说明:是
+
还是||
?
Access和SQL Server使用+
号。DB2、Oracle、PostgreSQL、SQLite和Open Office Base使用||
。
下面是使用加号的例子(多数DBMS使用这种语法):
SELECT vend_name + ' (' + vend_country + ')'
FROM Vendors
ORDER BY vend_name;
下面是相同的语句,但使用的是||
语法:
SELECT vend_name || ' (' || vend_country || ')'
FROM Vendors
ORDER BY vend_name;
RTRIM()
函数去掉值右边的所有空格。通过使用RTRIM()
,各个列都进行了整理。
说明:TRIM函数
大多数DBMS都支持RTRIM()
(正如刚才所见,它去掉字符串右边的空格)、LTRIM()
(去掉字符串左边的空格)以及TRIM()
(去掉字符串左右两边的空格)。
使用别名
SQL支持列别名。别名(alias)是一个字段或值的替换名。别名用AS关键字赋予。请看下面的SELECT语句:
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')'
AS vend_title
FROM Vendors
ORDER BY vend_name;
下面是相同的语句,但使用的是||
语法:
SELECT RTRIM(vend_name) || ' (' || RTRIM(vend_country) || ')'
AS vend_title
FROM Vendors
ORDER BY vend_name;
下面是MySQL和MariaDB中使用的语句:
SELECT Concat(vend_name, ' (', vend_country, ')')
AS vend_title
FROM Vendors
ORDER BY vend_name;
说明:AS通常可选
在很多DBMS中,AS关键字是可选的,不过最好使用它,这被视为一条最佳实践。提示:别名的其他用途
别名还有其他用途。常见的用途包括在实际的表列名包含不合法的字符(如空格)时重新命名它,在原来的名字含混或容易误解时扩充它。
警告:别名
别名既可以是一个单词也可以是一个字符串。如果是后者,字符串应该括在引号中。虽然这种做法是合法的,但不建议这么去做。多单词的名字可读性高,不过会给客户端应用带来各种问题。因此,别名最常见的使用是将多个单词的列名重命名为一个单词的名字。
说明:导出列
别名有时也称为导出列(derived column),不管怎么叫,它们所代表的是相同的东西。
7.3 执行算术计算
计算字段的另一常见用途是对检索出的数据进行算术计算。
SELECT prod_id,
quantity,
item_price,
quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
输出中显示的expanded_price列是一个计算字段,此计算为quantity*item_price。客户端应用现在可以使用这个新计算列,就像使用其他列一样。
基本算术操作符:+(加)、-(减)、*(乘)、/(除)。此外,圆括号可用来区分优先顺序。
提示:如何测试计算
SELECT
语句为测试、检验函数和计算提供了很好的方法。虽然SELECT
通常用于从表中检索数据,但是省略了FROM
子句后就是简单地访问和处理表达式,例如SELECT 3 * 2;
将返回6,SELECT Trim(' abc ');
将返回abc
,SELECT Now();
使用Now()
函数返回当前日期和时间。现在你明白了,可以根据需要使用SELECT
语句进行检验。
第8课 使用数据处理函数
8.1 函数
与大多数其他计算机语言一样,SQL也可以用函数来处理数据。函数一般是在数据上执行的,为数据的转换和处理提供了方便。
函数带来的问题
与几乎所有DBMS都等同地支持SQL语句(如SELECT)不同,每一个DBMS都有特定的函数。事实上,只有少数几个函数被所有主要的DBMS等同地支持。虽然所有类型的函数一般都可以在每个DBMS中使用,但各个函数的名称和语法可能极其不同。
函数 | 语法 |
---|---|
提取字符串的组成部分 | Access使用MID(); DB2、Oracle、PostgreSQL和SQLite使用SUBSTR(); MySQL和SQL Server使用SUBSTRING() |
数据类型转换 | Access和Oracle使用多个函数,每种类型的转换有一个函数; DB2和PostgreSQL使用CAST(); MariaDB、MySQL和SQL Server使用CONVERT() |
取当前时间 | Access使用NOW(); DB2和PostgreSQL使用CURRENT_DATE; MariaDB和MySQL使用CURDATE(); Oracle使用SYSDATE; SQL Server使用GETDATE(); SQLite使用DATE() |
与SQL语句不一样,SQL函数不是可移植的。这表示为特定SQL实现编写的代码在其他实现中可能不正常。
可移植(portable)
所编写的代码可以在多个系统上运行。
提示:是否应该使用函数?
现在,你面临是否应该使用函数的选择。决定权在你,使用或是不使用也没有对错之分。如果你决定使用函数,应该保证做好代码注释,以便以后你(或其他人)能确切地知道所编写的SQL代码的含义。
8.2 使用函数
大多数SQL实现支持以下类型的函数。
- 用于处理文本字符串(如删除或填充值,转换值为大写或小写)的文本函数。
- 用于在数值数据上进行算术操作(如返回绝对值,进行代数运算)的数值函数。
- 用于处理日期和时间值并从这些值中提取特定成分(如返回两个日期之差,检查日期有效性)的日期和时间函数。
- 返回DBMS正使用的特殊信息(如返回用户登录信息)的系统函数。
8.2.1 文本处理函数
RTRIM()
函数来去除列值右边的空格。
UPPER()
将文本转换为大写
SELECT vend_name, UPPER(vend_name) AS vend_name_upcase
FROM Vendors
ORDER