编写 SQL 查询:让我们从基础知识开始

简介

随着更强大的编程工具和环境(例如 Visual Basic 和 Visual Studio.NET)的出现,以及强大的数据库引擎(例如免费的 SQL Server 2005 Express Edition)的出现,越来越多的人发现需要学习 SQL 查询和语句的基础知识。有时是专业的开发人员,他们在其他类型的编程方面很有经验;有时是一些其他领域的专家,但是他们出于兴趣和/或益处,忽然发现他们自己需要编写数据库应用程序。如果您属于其中的一类,或者您只是对数据库编程感到好奇,则此文适合您阅读。

SQL Server 2005 Express 向您提供了一个深入了解高级数据库和数据库应用程序的机会(而且依然是免费的)。它与 SQL Server 2005 中所有其他版本的核心数据库引擎相同,但其安装和分发更简单,并且没有任何费用。它支持所有高级的数据库功能,包括视图、存储过程、触发器、函数、本机 XML 支持、完全 T-SQL 支持和高性能。

本文的目的是展示 SELECT 查询和语句的基本结构和用法。这些语句属于 Transact-SQL (T-SQL) 语言规范,也是使用 Microsoft SQL Server 的关键。T-SQL 是对 ANSI SQL 标准的扩展,进行了一些改进并添加了一些功能,使 T-SQL 成为一种数据访问和处理的高效、强大和安全的语言。

虽然设计查询时有许多可视化的工具可用(例如 Microsoft Visual Studio 提供的 Visual Database Tools),但是了解 SQL 语言依然是很值得的,也是很重要的。了解可视化工具的功能和原理确实能使您获益匪浅。有时候,手动编写所需 SQL 语句是唯一的(或只是最快的)得到所需结果的方法。它也是一种学习如何使用关系数据库(例如 SQL Express)的全部功能的理想方法。

关系数据库:30 秒回顾

虽然存在许多不同类型的数据库,但是我们将关注最常用的数据库类型:关系数据库。一个关系数据库由一个或多个表组成,其中每个表由 0 条或多条记录或数据行组成。每一行数据都被组织到离散的信息单元,称为“字段”或“列”。当我们希望显示表(例如 Customers 表)中的字段时,通常会如下所示:


 

一个数据库中的许多表之间将存在关系或链接,要么是一对一的关系,要么是一对多的关系。这些表是通过主键 - 外键对进行连接的,其中给定表中的外键字段为另一个表的主键。例如,Customers 和 Orders 之间存在着一对多的关系(这是一个典型的示例)。这两个表都有一个 CustID 字段,该字段既是 Customers 表的主键,也是 Orders 表的外键。这两个相关字段不需要具有相同的名称,不过建议使用相同的名称。

提取数据:SQL SELECT 查询

几乎所有的数据库应用程序在提取数据和显示数据时都需要很长时间。数据库中一旦有了数据,我们就会利用各种方法对数据进行“分割”和“切片”。也就是说,我们希望用各种不同的方法来查看和分析数据,需要经常改变应用到原始数据的筛选条件、排序方法和计算方法。SQL SELECT 语句就是我们要使用的语句,用于选择希望从数据库返回到应用程序的数据。我们使用这种语言来提出我们希望数据库答复的问题,也就是查询。我们可以从非常简单的查询开始,但 SELECT 语句有许多不同的选项和扩展项,它们可以向我们提供最终所需要的强大灵活性。我们的目标是帮助您了解 SELECT 语句的结构和最常用的元素,以便您能了解该语句的众多选项和其间的细微区别并能应用它们来满足您的特定需求。我们将从最简单的情况入手,慢慢添加选项来增强其功能。

请注意:为了便于说明,我们将使用 MS Access、MS SQL Server 附带的 Northwind 示例数据库中的 Employees 表,该表可以从 Microsoft 下载中心下载。

一条 SQL SELECT 语句可以分成许多元素,每个元素都以一个关键字开始。虽然没有硬性要求,但是习惯上这些关键字应该全部大写。在本文中,我们将关注 SELECT 语句最基础和最常用的元素,即:

SELECT

FROM

WHERE

ORDER BY

SELECT ...FROM 子句

最基本的 SELECT 语句仅有两个部分:(1) 要返回的列,和 (2) 这些列源于的表。

如果我们希望检索 Employees 表中所有客户的所有信息,我们可以使用星号 (*) 来简单地表示所有列,查询如下所示:

SELECT * FROM Employees

如果我们只需要特定列(通常情况下都是这样的),我们可以/应该在逗号分隔的列表中显式指定这些列,如下所示:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees

结果会显示该表中所有行的指定字段的数据:


 

显式指定所需字段还允许我们控制字段返回的顺序,如果我们希望姓显示在名之前,我们可以编写以下语句:

SELECT EmployeeID, LastName, FirstName, HireDate, City FROM Employees

WHERE 子句

接下来我们要做的是开始限制或筛选从数据库提取的数据。通过向 SELECT 语句添加 WHERE 子句,我们添加了一个(或多个)条件,所选数据必须满足这些条件。这将限制答复查询的行数以及被提取的行数。在许多情况下,大多数查询“操作”就是如此。

我们可以在上一个查询的基础上,将其限制为仅返回住在伦敦的员工:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
WHERE City = 'London'

结果如下:


 

如果您希望返回相反条件的员工,即返回那些不住在伦敦的员工,您应该编写以下语句:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
WHERE City <> 'London'

不需要测试等于情况,您也可以使用所需的标准等于/不等于运算符。例如,若要获取其雇佣日期等于某个给定日期或大于该日期的员工列表,您可以编写以下语句:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
WHERE HireDate >= '1-july-1993'

您可以得到以下结果行:


 

当然,我们可以编写更复杂的条件。有一个很明显的方法可以实现此目的:在 WHERE 子句中加入多个条件。如果我们希望了解哪些员工是在两个给定日期之间雇佣的,我们可以编写以下语句:

SELECT     EmployeeID, FirstName, LastName, HireDate, City
FROM       Employees
WHERE      (HireDate >= '1-june-1992') AND (HireDate <= '15-december-1993')

结果如下:


 

请注意,SQL 也有一个特殊的 BETWEEN 运算符,用于检查某个值是否在两个值之间(包括等于两端的值)。这使我们可以将以前的查询重新编写为:

SELECT    EmployeeID, FirstName, LastName, HireDate, City
FROM      Employees
WHERE     HireDate BETWEEN '1-june-1992' AND '15-december-1993'

我们也可以使用 NOT 运算符来提取那些不在指定日期之间的行:

SELECT    EmployeeID, FirstName, LastName, HireDate, City
FROM      Employees
WHERE     HireDate NOT BETWEEN '1-june-1992' AND '15-december-1993'

通过查看另外两个更复杂的比较运算符来结束此部分中对 WHERE 子句的介绍。

如果我们希望检查一个列值是否等于多个值,那该怎么办呢?如果只是两个值,则很容易对每个值进行测试,方法是,使用 OR 运算符将它们连接在一起,则编写的语句如下所示:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
WHERE City = 'London' OR City = 'Seattle'

但是,如果您希望与三个、四个或更多值进行比较,则上述方法就行不通了。在这种情况下,我们可以使用 IN 运算符来对一组值进行测试。如果我们希望查看 City 是否为 Seattle、Tacoma 或 Redmond,我们可以编写以下语句:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
WHERE City IN ('Seattle', 'Tacoma', 'Redmond')

显示以下结果:


 

有了 BETWEEN 运算符,我们也可以获得所含结果的相反条件下的结果,即查询那些 City 不在指定列表中的行:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
WHERE City NOT IN ('Seattle', 'Tacoma', 'Redmond')

最后要说明的是,LIKE 运算使我们可以使用通配符来执行基本的模式匹配。在 Microsoft SQL Server 中,定义的通配符包含以下字符:

通配符说明

_(下划线)

与任意单字符匹配

%

与包含一个或多个字符的字符串匹配

[ ]

与特定范围(例如,[a-f])或特定集(例如,[abcdef])中的任意单字符匹配。

[^]

与特定范围(例如,[^a-f])或特定集(例如,[^abcdef])之外的任意单字符匹配。

以下一些示例可以帮助阐明上述规则。

WHERE FirstName LIKE '_im' 可以找到所有三个字母的、以 im 结尾的名字(例如,Jim、Tim)。

WHERE LastName LIKE '%stein' 可以找到姓以 stein 结尾的所有员工。

WHERE LastName LIKE '%stein%' 可以找到姓中任意位置包括 stein 的所有员工。

WHERE FirstName LIKE '[JT]im' 可以找到三个字母的、以 im 结尾并以 J 或 T 开始的名字(即仅有 Jim 和 Tim)

WHERE LastName LIKE 'm[^c]%' 可以找到以 m 开始的、后面的(第二个)字母不为 c 的所有姓。

此处我们也选择使用 NOT 运算符:若要找到所有名字不以 M 或 A 开始的员工,我们可以编写以下语句:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
WHERE (FirstName NOT LIKE 'M%') AND (FirstName NOT LIKE 'A%')

结果如下:


 

ORDER BY 子句

直到现在我们一直在讨论筛选数据:即定义一些条件,来确定哪些行将包括在从数据库提取并返回的最终行集中。一旦我们确定了哪些列和行将包括在 SELECT 查询的结果中,我们可能就希望控制这些行显示的顺序:对数据排序。

若要对数据行排序,我们需要 ORDER BY 子句。ORDER BY 子句包括了一个或多个用于指定排序顺序的列名。如果返回至第一批 SELECT 语句中的某条语句,我们可以用以下语句按 City 对其结果排序:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
ORDER BY City

默认情况下,列的排序顺序为升序(从最小值到最大值),上述查询的结果如下所示:


 

如果我们希望列的排序顺序为降序,我们可以在列名后包括 DESC 关键字。

ORDER BY 子句支持使用多列。您可以包括以逗号分隔的多个列以按其排序:行将先按指定的第一列进行排序,然后再按指定的下一列进行排序。如果我们向 SELECT 子句添加 Country 字段并希望按 Country 和 City 排序,我们可以编写以下语句:

SELECT EmployeeID, FirstName, LastName, HireDate, Country, City FROM Employees
ORDER BY Country, City DESC

请注意,为了使语句显得更有趣,我们已经指定了 City 列的排序顺序为降序(从最大值到最小值)。Country 列的排序顺序仍为升序。通过编写以下语句我们可以更清楚地了解到这一点:

SELECT EmployeeID, FirstName, LastName, HireDate, Country, City FROM Employees
ORDER BY Country ASC, City DESC

但这不是必要的,并且很少这么做。此查询返回的结果如下所示:


 

重要的是要注意要在 ORDER BY 子句中使用某一列时,并不需要在选定的(返回的)多个列中包括这一列。如果我们不需要查看/使用 Country 值,只是对于将其作为主排序字段感兴趣,可以编写以下查询:

SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees
ORDER BY Country ASC, City DESC

所得结果的排序顺序与上一个查询所得结果的排序顺序相同:


 

结论

在本文中,我们了解了用于常见数据库查询任务的 SQL SELECT 语句最基本的元素。包括如何指定和筛选查询要返回的列和行。我们还了解了如何控制所返回行的顺序。

虽然此处讨论的元素使您可以完成许多数据访问/查询任务,但是 SQL SELECT 语句还有更多的选项和其他功能。其他功能包括分组和聚合数据(对数据进行汇总、计数和分析,例如最小值、最大值和平均值)。本文并未涉及从关系数据库提取数据的另一个基本的方面:从多个表选择数据。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值