第1课 SQL入门之了解SQL
第2课 SQL入门之检索数据
第3课 SQL入门之排序检索数据
第4课 SQL入门之过滤数据
第5课 SQL入门之高级数据过滤
第6课 SQL入门之用通配符进行过滤
第7课 SQL入门之创建计算字段
第8课 SQL入门之使用数据处理函数
第9课 SQL入门之汇总数据
第10课 SQL入门之分组数据
第11课 SQL入门之使用子查询
第12课 SQL入门之联结表
第13课 SQL入门之创建高级联结
第14课 SQL入门之组合查询
第15课 SQL入门之插入数据
第16课 SQL入门之更新和删除数据
第17课 SQL入门之创建和操纵表
第18课 SQL入门之使用视图
第19课 SQL入门之使用存储过程
第20课 SQL入门之管理事务处理
第21课 SQL入门之使用游标
第22课 SQL入门之高级SQL特性
附录A SQL入门之SQL样例表脚本
附录B SQL入门之SQL流行的应用程序
附录C SQL入门之SQL语句的语法
附录D SQL入门之SQL数据类型
附录E SQL入门之SQL保留字
正如第1课所述,SQL语句是由简单的英语单词构成的。这些单词称为关键字,每个SQL语句都是由一个或多个关键字构成的。最经常使用的SQL语句大概就是SELECT语句了。它的用途是从一个或多个表中检索信息。
关键字(keyword) 作为SQL组成部分的保留字。关键字不能用作表或列的名字。附录E列出了某些经常使用的保留字。
为了使用SELECT检索表数据,必须至少给出两条信息——想选择什么,以及从什么地方选择。
说明:理解例子
本专栏各课程中的样例SQL语句(和样例输出)使用了附录A中描述的一组数据文件。如果想要理解和试验这些样例(我强烈建议这样做),请参阅附录A,它解释了如何下载或创建这些数据文件。
重要的是,要理解SQL是一种语言而不是一个应用程序。具体如何写SQL语句并显示语句输出,是随不同的应用程序而变化的。为帮助读者根据自己的环境使用相应的例子,附录B介绍了如何针对许多流行的应用程序及开发环境发出本专栏中介绍的语句。如果读者需要了解某个应用程序,附录B中也给出了相应的建议。
我们将从简单的SQL SELECT语句讲起,此语句如下所示:
输入▼
SELECT prod_name FROM Products;
分析▼
上述语句利用SELECT语句从Products表中检索一个名为prod_name的列。所需的列名写在SELECT关键字之后,FROM关键字指出从哪个表中检索数据。此语句的输出如下所示:
输出▼
prod_name
-------------------
Fish bean bag toy
Bird bean bag toy
Rabbit bean bag toy
8 inch teddy bear
12 inch teddy bear
18 inch teddy bear
Raggedy Ann
King doll
Queen doll
提示:未排序数据 如果你自己试验这个查询,可能会发现显示输出的数据顺序与这里的不同。出现这种情况很正常。如果没有明确排序查询结果(下一课介绍),则返回的数据没有特定的顺序。返回数据的顺序可能是数据被添加到表中的顺序,也可能不是。只要返回相同数目的行,就是正常的。
如上的一条简单SELECT语句将返回表中的所有行。数据没有过滤(过滤将得出结果集的一个子集),也没有排序。以后几课将讨论这些内容。
提示:结束SQL语句
多条SQL语句必须以分号(;)分隔。多数DBMS不需要在单条SQL语句后加分号,但也有DBMS可能必须在单条SQL语句后加上分号。当然,如果愿意可以总是加上分号。事实上,即使不一定需要,加上分号也肯定没有坏处。
提示:SQL语句和大小写 请注意,SQL语句不区分大小写,因此SELECT与select是相同的。同样,写成Select也没有关系。许多SQL开发人员喜欢对SQL关键字使用大写,而对列名和表名使用小写,这样做使代码更易于阅读和调试。不过,一定要认识到虽然SQL是不区分大小写的,但是表名、列名和值可能有所不同(这有赖于具体的DBMS及其如何配置)。
提示:使用空格
在处理SQL语句时,其中所有空格都被忽略。SQL语句可以写成长长的一行,也可以分写在多行。下面这三种写法的作用是一样的。
SELECT prod_name FROM Products;
SELECT prod_name FROM Products;
SELECT prod_name
FROM Products;
多数SQL开发人员认为,将SQL语句分成多行更容易阅读和调试。
要想从一个表中检索多个列,仍然使用相同的SELECT语句。唯一的不同是必须在SELECT关键字后给出多个列名,列名之间必须以逗号分隔。
提示:当心逗号
在选择多个列时,一定要在列名之间加上逗号,但最后一个列名后不加。如果在最后一个列名后加了逗号,将出现错误。
下面的SELECT语句从Products表中选择3列。
输入▼
SELECT prod_id, prod_name, prod_price
FROM Products;
分析▼
与前一个例子一样,这条语句使用SELECT语句从表Products中选择数据。在这个例子中,指定了3个列名,列名之间用逗号分隔。此语句的输出如下:
输出▼
prod_id prod_name prod_price
--------- -------------------- ----------
BNBG01 Fish bean bag toy 3.4900
BNBG02 Bird bean bag toy 3.4900
BNBG03 Rabbit bean bag toy 3.4900
BR01 8 inch teddy bear 5.9900
BR02 12 inch teddy bear 8.9900
BR03 18 inch teddy bear 11.9900
RGAN01 Raggedy Ann 4.9900
RYL01 King doll 9.4900
RYL02 Queen dool 9.4900
说明:数据表示
从上述输出可以看到,SQL语句一般返回原始的、无格式的数据。数据的格式化是表示问题,而不是检索问题。因此,表示(如把上面的价格值显示为正确的十进制数值货币金额)一般在显示该数据的应用程序中规定。通常很少直接使用实际检索出的数据(没有应用程序提供的格式)。
除了指定所需的列外(如上所述,一个或多个列),SELECT语句还可以检索所有的列而不必逐个列出它们。在实际列名的位置使用星号(*)通配符可以做到这点,如下所示。
输入▼
SELECT *
FROM Products;
分析▼
如果给定一个通配符(*),则返回表中所有列。列的顺序一般是列在表定义中出现的物理顺序,但并不总是如此。不过,SQL数据很少这样(通常,数据返回给应用程序,根据需要进行格式化,再表示出来)。因此,这不应该造成什么问题。
警告:使用通配符
一般而言,除非你确实需要表中的每一列,否则最好别使用*通配符。虽然使用通配符能让你自己省事,不用明确列出所需列,但检索不需要的列通常会降低检索和应用程序的性能。
提示:检索未知列 使用通配符有一个大优点。由于不明确指定列名(因为星号检索每一列),所以能检索出名字未知的列。
如前所述,SELECT语句返回所有匹配的行。但是,如果你不希望每个值每次都出现,该怎么办呢?例如,你想检索products表中所有产品供应商的ID:
输入▼
SELECT vend_id
FROM Products;
输出▼
vend_id |
---|
BRS01 |
BRS01 |
BRS01 |
DLL01 |
DLL01 |
DLL01 |
DLL01 |
FNG01 |
FNG01 |
SELECT语句返回9行(即使表中只有3个产品供应商),因为products表中有9种产品。那么如何检索出不同的值?
办法就是使用DISTINCT关键字,顾名思义,它指示数据库只返回不同的值。
输入▼
SELECT DISTINCT vend_id
FROM Products;
分析▼ SELECT DISTINCT vend_id告诉DBMS只返回不同(具有唯一性)的vend_id行,所以正如下面的输出,只有3行。如果使用DISTINCT关键字,它必须直接放在列名的前面。
输出▼
vend_id |
---|
BRS01 |
DLL01 |
FNG01 |
警告:不能部分使用DISTINCT DISTINCT关键字作用于所有的列,不仅仅是跟在其后的那一列。例如,你指定SELECT DISTINCT vend_id, prod_price,除非指定的两列完全相同,否则所有的行都会被检索出来。
SELECT语句返回指定表中所有匹配的行,很可能是每一行。如果你只想返回第一行或者一定数量的行,该怎么办呢?这是可行的,然而遗憾的是,各种数据库中的这一SQL实现并不相同。
在SQL Server和Access中使用SELECT时,可以使用TOP关键字来限制最多返回多少行,如下所示:
输入▼
SELECT TOP 5 prod_name
FROM Products;
输出▼
prod_name |
---|
8 inch teddy bear |
12 inch teddy bear |
18 inch teddy bear |
Fish bean bag toy |
Bird bean bag toy |
分析▼
上面代码使用SELECT TOP 5语句,只检索前5行数据。
如果你使用的是DB2,很可能习惯使用下面这一DBMS特定的SQL语句,像这样:
输入▼
SELECT prod_name
FROM Products FETCH FIRST 5 ROWS ONLY;
分析▼
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;
分析▼
上述代码使用SELECT语句来检索单独的一列数据。LIMIT 5指示MySQL等DBMS返回不超过5行的数据。这个语句的输出参见下面的代码。
为了得到后面的5行数据,需要指定从哪儿开始以及检索的行数,像这样:
输入▼
SELECT prod_name FROM Products LIMIT 5 OFFSET 5;
分析▼
LIMIT 5 OFFSET 5指示MySQL等DBMS返回从第5行起的5行数据。第一个数字是指从哪儿开始,第二个数字是检索的行数。这个语句的输出是:
输出▼
prod_name |
---|
Rabbit bean bag toy |
Raggedy Ann |
King doll |
Queen doll |
所以,LIMIT指定返回的行数。带OFFSET的LIMIT指定从哪儿开始。在我们的例子中,Products表中只有9种产品,所以LIMIT 5 OFFSET 5只返回了4行数据(因为没有第5行)。
警告:第0行 第一个被检索的行是第0行,而不是第1行。因此,LIMIT 1 OFFSET 1会检索第2行,而不是第1行。
提示:MySQL和MariaDB快捷键 MySQL和MariaDB支持简化版的LIMIT 4 OFFSET 3语句,即LIMIT 3,4。使用这个语法,,之前的值对应LIMIT, ,之后的值对应OFFSET。
说明:并非所有的SQL实现都一样 我加入这一节只有一个原因,就是要说明,SQL虽然通常都有相当一致的实现,但你不能想当然地认为它总是这样。非常基本的语句往往是容易移植的,但较复杂的语句就不同了。当你针对某个问题寻找SQL解决方案时,一定要记住这一点。
可以看到,SQL语句是由DBMS处理的指令。如果你希望包括不进行处理和执行的文本,该怎么办呢?为什么你想要这么做呢?原因有以下几点。
• 我们这里使用的SQL语句都很短,也很简单。然而,随着你的SQL语句变长,复杂性增加,你就会想添加一些描述性的注释,这便于你自己今后参考,或者供项目后续参与人员参考。这些注释需要嵌入在SQL脚本中,但显然不能进行实际的DBMS处理。(相关示例可以参见附录B中使用的create.sql和populate.sql。)
• 这同样适用于SQL文件开始处的内容,它可能包含程序员的联系方式、程序描述以及一些说明。(相关示例也可参见附录B中的那些.sql文件。)
• 注释的另一个重要应用是暂时停止要执行的SQL代码。如果你碰到一个长SQL语句,而只想测试它的一部分,那么应该注释掉一些代码,以便MariaDB将其视为注释而加以忽略。
很多DBMS都支持各种形式的注释语法。我们先来看行内注释:
输入▼
SELECT prod_name -- 这是一条注释
FROM Products;
分析▼
注释使用-- (两个连字符)嵌在行内。-- 之后的文本就是注释,例如,这用来描述CREATE TABLE语句中的列就很不错。
下面是另一种形式的行内注释(虽然这种形式很少得到支持)。
输入▼
#这是一条注释
SELECT prod_name
FROM Products;
分析▼
在一行的开始处使用#,这一整行都将作为注释。你在本专栏提供的脚本create.sql和populate.sql中可以看到这种形式的注释。
你也可以进行多行注释,注释可以在脚本的任何位置停止和开始。
输入▼
/* SELECT prod_name, vend_id
FROM Products; */
SELECT prod_name
FROM Products;
分析▼
注释从/开始,到/结束,/和/之间的任何内容都是注释。这种方式常用于给代码加注释,就如这个例子演示的,这里定义了两个SELECT语句,但是第一个不会执行,因为它已经被注释掉了。
下一篇:第1课 SQL入门之了解SQL
下一篇:第3课 SQL入门之排序检索数据