通往到T-SQL DML级别1的阶梯:基本选择语句
作者:格雷戈里拉森 ,
2011/10/07
系列
以下是在这阶梯系列中将涵盖的不同级别:
· 级别 6: 使用 order by 子句对数据进行排序的基础知识
· 级别 7: 使用简单分组 order by 子句汇总数据
· 级别 8: 数据修改: 更新
· 级别 9: 数据修改: 删除
从单个表返回数据的基本 SELECT 语句由三个不同的部分组成: 列-列表、from 子句和 where 子句。使用这些不同的组件构造基本 SELECT 语句的语法如下所示:
SELECT <Column List>FROM <table name>WHERE <where criteria>;
"< 列-列表 >" 将包含您希望从查询返回的列的列表, "<列表名 >" 将包含从中选择数据的表, 而 "< where 条件 >" 清楚地标识将用于约束SELECT 语句而返回的行。请注意, where 子句是可选的。
请注意, 此文章中的所有示例都将使用AdventureWorks SQL server 2005 数据库, 可在该网址获取: http://sqlserversamples.codeplex.com/ .
让我们看看下面的非常简单的 SELECT 语句, 它可以从AdventureWorks数据库中的表中选择一些数据。通过在 SQL server 管理工作室中使用查询窗口运行本文描述的每个查询语句, 并将数据库设置为AdventureWorks , 您可以继续执行此项工作。.
SELECT ProductCategoryID ,
NameFROM Production.ProductCategoryWHERE ProductCategoryID < 2 ;
在这里, 我从生产.种类表中选择了两个不同的列种类ID和名称。由于此 SELECT 语句具有 where 子句, 因此它将从表返回的行限制为只有种类ID值小于2的行。
现在, 您已经有了一个 select 语句的基本概念, 接下来我将更详细地探讨 select 语句的每个组件。
列-列表
列-列表遵循 SELECT 关键字, 并且指定要从表中返回的列的位置。通过指定列名来标识列。如果列中出了多个列, 它们将用逗号隔开。在以后的级别中, 我们将研究从指定表中返回除列以外的值的可能性, 在第一级, 我们将坚持基本知识。在上面的示例中, 让我们来探讨列如果它只选择一列或表的所有列时列表的外观, 如果我只想返回生产.种类表的名称列, 那么我的查询将如下所称:
SELECT NameFROM Production.ProductCategoryWHERE ProductCategoryID < 2 ;
在这里, 您可以看到, 我只指定了上面查询中的 "选择" 和 "从" 关键字之间的Name列。但是, 如果我想指定生产种类表中的所有列, 我将运行以下查询:
SELECT ProductCategoryID ,
Name ,
rowguid ,
ModifiedDateFROM Production.ProductCategoryWHERE ProductCategoryID < 2 ;
在这个 SELECT 语句中, 您可以看到, 我已经确定了4个不同的列, 每一个都用逗号隔开。正如我所做的那样, 这些列可以一起列在一行上, 或者在不同的行上分开以获得可读性。还有另一种方法可以从表中选择所有列, 即指定星号而不是指定单个列名。下面是一个使用星号规范的 SELECT 语句:
SELECT *FROM Production.ProductCategoryWHERE ProductCategoryID < 2 ;
在应用程序中使用星号 (通常称为 "星级") 时需要注意。由于星号将返回表中的所有列, 因此如果发生更改表以包含附加列, 则将返回附加列而不修改实际 SELECT 语句。而如果您已按名称指定了所有列, 则在添加新列时将不会返回, 除非将其添加到列列表中。可以使用星号进行测试, 但如果要遵循最佳的做法, 请不要在应用程序代码中使用。这是最佳做法的原因是, 大多数应用程序都希望从给定 SELECT 语句返回固定数目的列。当列添加到表中并使用星号方法标识表列时, 返回的其他列可能会中断尚未编码以处理此额外数据的应用程序。
FROM 子句
在FROM子句中,标识要从中选择数据的表。在这个级别上,我们只讨论从FROM子句中的单个表中选择数据。请注意,随着您对SQL的了解不断加深,FROM子句可以标识要从中选择数据的多个表。
有许多不同的方法来标识要在其中选择数据的表。事实上,有四种不同的方法,我将在本文中介绍其中的三种,第四种方法是通过标识表名和表所属的架构来指定表。
第一种方法是通过标识表名及其所在的模式来指定表。这就是我在所有示例中识别出所有表名的方法。在我的每个例子中,我说的表名是Production.Productcategory。实际的表名是Production.Productcategory,它包含在生产模式中。
识别FROM子句中的表的第二种方法是只声明表名。当FROM子句仅包含表名时,SQLServer将假定该表包含在数据库用户的默认架构下或DBO模式下。让我更详细地解释一下这个概念。
当您向仅标识表名的SQLServer提交查询时,SQLServer将需要解析该表所处的架构。这是因为在给定的数据库中可以有多个同名的表,只要它们在不同的模式中。要确定一个表驻留在SQLServer中的架构,需要经过两个步骤。第一步是对提交查询的数据库用户使用默认架构,并附加他们的默认架构名,然后查找该表。如果SQLServer使用用户默认架构找到表,则不执行步骤二。如果SQLServer没有使用用户默认架构找到表,则SQLServer将检查DBO架构以查找表。无论您的数据库是否包含单个模式,最好的做法是习惯于使用模式名称后面的表名来标识FROM子句中的表。通过这样做,您可以减少SQLServer解析表名和促进计划缓存重新使用所需的工作量。
识别表的第三种方法是使用三个部件名,其中最后两个部分是架构和表名,第一部分是数据库名。下面是一个SELECT语句,类似于我以前的SELECT语句,它使用了三个部分的名称:
SELECT *FROM AdventureWorks.Production.ProductCategoryWHERE ProductCategoryID < 2 ;
在这里,您可以看到,我将数据库名AdventureWorks附加到FROM条款中标识的Production.ProductClass表中。
通过使用FROM子句中表的三部分命名约定,SQL Server Management Studio中查询窗口的数据库上下文可以设置为任何数据库,数据库引擎仍将知道要用于查询的数据库、架构和表。当构建需要从实例中的多个数据库检索数据的应用程序时,使用三个部件名称有助于从单个应用程序中的多个数据库检索数据。
最后一种方法是使用四部分的名称,第四部分(在数据库名称之前)标识链接服务器的名称。由于链接服务器超出了本阶梯的范围,我将不再进一步讨论这个主题。如果您应该跨包含4个部分的表名运行,您将知道该表与链接服务器相关联。
WHERE 子句
SELECT语句的WHERE子句是可选的。WHERE子句用于约束SELECT语句返回的行。数据库引擎根据WHERE子句计算每一行,然后只返回符合WHERE子句中标识的搜索条件的行。当您编写更多SELECT语句时,您会发现大多数SELECT语句可能包含WHERE子句。
简单WHERE子句将包含单个搜索条件,而更复杂的WHERE子句可能包含许多条件。当在WHERE子句中使用多个条件时,它们将通过使用AND和OR逻辑运算符逻辑地组合在一起。SELECT语句中可能包含的不同条件的数量没有限制。在我的例子中,到目前为止,我只使用了一个条件。下面是一个SELECT语句,它有两个不同的搜索条件:
SELECT *FROM Production.ProductWHERE Color = 'Blue'
AND ProductID > 900 ;
在这个语句中,第一个条件检查行是否在Color列中有值Blue。第二个条件检查Productid列中的值是否大于900。由于使用了and操作符,为了从这个查询返回一行,这两个条件都必须为true。
此示例返回Production.Product行,其中Productid值大于900,颜色列中的值为Blue或Green。通过查看这个查询,您可以看到我在两个不同的Color条件周围放置了括号。设置了条件之间相互评估的顺序,就像在数学表达式中所做的那样。通过使用括号,在计算AND运算符之前,将计算两种颜色条件之间的OR操作。在不带括号的情况下使用AND和OR时,这些逻辑运算符是进程的顺序是基于逻辑运算符优先的规则。优先级规则规定,如果不包含括号,则在OR操作之前执行操作。让我在前面的WHERE子句的基础上添加一个NOT操作符:
SELECT *FROM Production.ProductWHERE ProductID > 900
AND ( Color = 'Blue'
OR Color = 'Green'
) ;
我在操作和操作之后添加了非操作符,表明我想要的不是蓝色或绿色的产品。当我运行这个查询我的AdventureWorks数据库我知道是银色,黄色和黑色。
通过查看这个查询,您可以看到我在两个不同的Color条件周围放置了括号。设置了条件之间相互评估的顺序,就像在数学表达式中所做的那样。通过使用括号,在计算AND运算符之前,将计算两种颜色条件之间的OR操作。在不带括号的情况下使用AND和OR时,这些逻辑运算符是进程的顺序是基于逻辑运算符优先的规则。优先级规则规定,如果不包含括号,则在OR操作之前执行操作。让我在前面的WHERE子句的基础上添加一个NOT操作符:
SELECT Name ,
ColorFROM Production.ProductWHERE ProductID > 900
AND NOT ( Color = 'Blue'
OR Color = 'Green'
) ;
我在操作和操作之后添加了非操作符,表明我想要的不是蓝色或绿色的产品。当我运行这个查询我的AdventureWorks数据库我知道是银色,黄色和黑色。
把它们放在一起:业务案例
现在轮到您使用我共享的信息来构建您自己的基本选择语句了。在本节中,我将为您提供一些练习,您可以练习编写选择语句来满足所描述的业务案例。
练习# 1:
假设你已经被人力资源部的负责人要求为那些有大量病假和休假时间的员工列出所有员工的价值观。为了达到这个列表的目的,人力资源主管告诉你“大量休假”的定义如下:员工必须有超过68小时的病假价值,而休假时间的价值大于98。您可以在人力资源中找到这些栏目以及员工ID专栏。员工表。在冒险工作数据库中编写和测试你的代码。完成后,在下面的小节中检查您的代码。
练习# 2:
你的经理对一些特定的订单号有一些问题。您的经理希望您生成一个列表,其中列出了与几个特定订单相关的所有列,这样她就可以检查哪些销售人员与每个订单相关联。您的经理指定她只对一个包含销售订单的报告感兴趣,该报告的订单在43702和43712之间有一个销售订单id。当您完成这个选择语句的编写时,请检查下面的答案。
答案练习# 1:
SELECT EmployeeID ,
SickLeaveHours ,
VacationHoursFROM HumanResources.EmployeeWHERE SickLeaveHours >68
AND VacationHours >98;
你的查询应该是这样的:
您的查询的结果应该返回以下三行:
EmployeeID SickLeaveHours VacationHours
----------- -------------- -------------
109 69 99
179 69 99
224 69 99
练习2的答案:
如果您阅读上面提到的文档,您的查询应该是这样的,以便了解更多关于搜索条件和操作符之间的信息:
SELECT*FROM Sales.SalesOrderHeaderWHERE SalesOrderID BETWEEN43702AND43712;
或者您可能已经编写了类似于此的代码:
SELECT SalesOrderID ,
RevisionNumber ,
OrderDate ,
DueDate ,
ShipDate ,
Status ,
OnlineOrderFlag ,
SalesOrderNumber ,
PurchaseOrderNumber ,
AccountNumber ,
CustomerID ,
ContactID ,
SalesPersonID ,
TerritoryID ,
BillToAddressID ,
ShipToAddressID ,
ShipMethodID ,
CreditCardID ,
CreditCardApprovalCode ,
CurrencyRateID ,
SubTotal ,
TaxAmt ,
Freight ,
TotalDue ,
Comment ,
rowguid ,
ModifiedDateFROM Sales.SalesOrderHeaderWHERE SalesOrderID >=43702
AND SalesOrderID <=43712;
您的查询应该返回11行。5行有一个订单日期2001-07-02,5行有一个订单日期是 2001-07-03,2行有一个订单日期是2001-07-04。
关于这个解决方案与前一个解决方案,所有列名都被标识,而前面的解决方案使用星号来指定所有列。通过名称来标识所有列是一种更好的编码实践,因为您的选择语句总是会返回相同数量的栏目,即使添加了额外的列到您的表中。当您的应用程序期望从您的选择语句中返回特定数量的列时,这一点很重要。
理解基本选择语句
为了成为一个SQL Server应用程序程序员,您首先需要了解基本的选择语句。理解如何检索表格中的所有数据并限制返回的内容是开发应用程序的基础。本文以及练习为您提供了选择语句的基础知识,这是本系列的第一个构建块。