SQLServer 2000:SELECT 语句的各部分1

SELECT 语句的各部分

虽然 SELECT 语句的完整语法较复杂,但是其主要的子句可归纳如下:

SELECT select_list
[INTO new_table_name]
FROM table_list
[WHERE search_conditions]
[GROUP BY group_by_list]
[HAVING search_conditions]
[ORDER BY order_list [ASC | DESC] ]

select_list

描述结果集的列。它是一个逗号分隔的表达式列表。每个表达式同时定义格式(数据类型和大小)和结果集列的数据来源。每个选择列表表达式通常是对从中获取数据的源表或视图的列的引用,但也可能是其它表达式,例如常量或 Transact-SQL 函数。在选择列表中使用 * 表达式指定返回源表中的所有列。

INTO new_table_name

指定使用结果集来创建新表。new_table_name 指定新表的名称。

FROM table_list

包含从中检索到结果集数据的表的列表。这些来源可能包括:

  • 运行 Microsoft® SQL Server™ 的本地服务器中的基表。

  • 本地 SQL Server 中的视图。SQL Server 将一个视图引用内部解析为针对组成视图的基表的多个引用。

  • 链接表是可从 SQL Server 进行访问的 OLE DB 数据源中的表。这种访问方式称为分布式查询。通过将 OLE DB 数据源链接为链接服务器或者在 OPENROWSET 或 OPENQUERY 函数中引用数据源,可实现从 SQL Server 访问 OLE DB 数据源。

    FROM 子句还可包含联接说明,该说明定义了 SQL Server 用来在表之间进行导航的特定路径。

    FROM 子句还用在 DELETE 和 UPDATE 语句中以定义要修改的表。

WHERE search_conditions

WHERE 子句是一个筛选,它定义了源表中的行要满足 SELECT 语句的要求所必须达到的条件。只有符合条件的行才向结果集提供数据。不符合条件的行中的数据不会被使用。

WHERE 子句还用在 DELETE 和 UPDATE 语句中以定义目标表中要修改的行。

GROUP BY group_by_list

GROUP BY 子句根据 group_by_list 列中的值将结果集分成组。例如,Northwind Orders 表在 ShipVia 中有三个值。GROUP BY ShipVia 子句将结果集分成三组,每组对应于 ShipVia 的一个值。

HAVING search_conditions

HAVING 子句是应用于结果集的附加筛选。逻辑上讲,HAVING 子句从中间结果集对行进行筛选,这些中间结果集是用 SELECT 语句中的 FROM、WHERE 或 GROUP BY 子句创建的。HAVING 子句通常与 GROUP BY 子句一起使用,尽管 HAVING 子句前面不必有 GROUP BY 子句。

ORDER BY order_list [ ASC | DESC ]

ORDER BY 子句定义结果集中的行排列的顺序。order_list 指定组成排序列表的结果集的列。ASC 和 DESC 关键字用于指定行是按升序还是按降序排序。

ORDER BY 之所以重要,是因为关系理论规定除非已经指定 ORDER BY,否则不能假设结果集中的行带有任何序列。如果结果集行的顺序对于 SELECT 语句来说很重要,那么在该语句中就必须使用 ORDER BY 子句。

必须按照正确的顺序指定 SELECT 语句中的子句。

对数据库对象的每个引用都不得引起歧义。下列情况可能会导致多义性:

  • 在系统中,可能有多个对象带有相同的名称。例如,User1User2 可能都指定了一个名为 TableX 的表。若要解析多义性并且指定 TableX User1 所有,请至少使用用户 ID 来限定表的名称:
    SELECT *
    FROM User1.TableX
    
  • 在执行 SELECT 语句时,对象所驻留的数据库不一定总是当前数据库。若要确保总是使用正确的对象,则不论当前数据库是如何设置的,均应使用数据库和所有者来限定对象名称:
    SELECT *
    FROM Northwind.dbo.Shippers
    
  • 在 FROM 子句中所指定的表和视图可能有相同的列名。外键很可能具有和相关主键相同的列名。若要解析重复名称之间的多义性,必须使用表或视图名称来限定列名:
    SELECT DISTINCT Customers.CustomerID, Customers.CompanyName
    FROM Customers JOIN Orders ON
           ( Customers.CustomerID = Orders.CustomerID)
    WHERE Orders.ShippedDate > 'May 1 1998'
    

    当必须完全限定表和视图名称本身时,上述语法会变得很烦琐。通过在 FROM 子句中使用 AS 关键字为表指派一个相关名称(也称为范围变量或别名)即可解决此问题。只能在 FROM 子句中定义完全合法的表或视图名称。然后所有其它表或视图引用都可使用此相关名称。在前一个示例中应用相关名称并且完全限定表,会有如下的 SELECT 语句:

    SELECT DISTINCT Cst.CustomerID, Cst.CompanyName
    FROM Northwind.dbo.Customers AS Cst
       JOIN
         Northwind.dbo.Orders AS Ord
       ON ( Cst.CustomerID = Ord.CustomerID)
    WHERE Ord.ShippedDate > 'May 1 1998'
    

    使用选择列表

    选择列表可定义 SELECT 语句的结果集中的列。选择列表是以逗号分隔的一系列表达式。每个表达式定义结果集中的一列。结果集中列的排列顺序与选择列表中表达式的排列顺序相同。

    结果集列的这些特性由选择列表中的下列表达式定义:

    • 结果集列的数据类型、大小、精度以及小数位数与定义列的表达式相同。

    • 结果集列的名称与定义列的表达式名称相关联。可选的 AS 关键字可用于更改名称,或当表达式没有名称时为其指定一个名称。

    • 结果集列的数据值出自结果集的每一行的表达式的取值。

    选择列表还可包含控制结果集的最终格式的关键字:

    • DISTINCT

      DISTINCT 关键字可从结果集中除去重复的行。例如,在 Northwind Orders 表中有许多行的 ShipCity 值是相同的。若要获得已删除重复内容的 ShipCity 值列表,请用如下语句:

      SELECT DISTINCT ShipCity, ShipRegion
      FROM Orders
      ORDER BY ShipCity
      
    • TOP n

      TOP 关键字指定返回结果集的前 n 行。如果指定了 ORDER BY,行将在结果集排序之后选定。除非指定了 PERCENT 关键字,否则 n 即为返回的行数。PERCENT 指定 n 为结果集中返回的行的百分比。例如,SELECT 语句从 Orders 表中按照字母顺序返回前 10 个城市:

      SELECT DISTINCT TOP 10 ShipCity, ShipRegion
      FROM Orders
      ORDER BY ShipCity
      

    选择列表中的项目可包括:

    • 简单表达式:对函数、局部变量、常量或者表或视图中的列的引用。

    • 标量子查询是对结果集的每一行求得单值的 SELECT 语句。

    • 通过对一个或多个简单表达式使用运算符创建的复杂表达式。

    • 使用 * 关键字将返回表中的所有列。

    • @local_variable = expression 形式的变量赋值。SET @local_variable 语句还可用于变量赋值。

    • IDENTITYCOL 关键字将被解析为对具有 IDENTITY 属性的表中的列的引用。例如,已经为 Northwind Orders 表中的 OrderID 列定义了 IDENTITY 属性,这样,表达式 Orders.IDENTITYCOL 等同于 Orders.OrderID

    • ROWGUILDCOL 关键字被解析为对表中具有 ROWGUIDCOL 属性的列的引用。

    • 按照规定的语法,创建一个使用 IDENTITY 属性的新列(使用 SELECT INTO)。例如,若要在 authors 表中新建一列,其名称为 counter,数据类型为 int,并从数值 100 开始使后面的数字依次递增 1,应该使用 counter = IDENTITY(int, 100, 1)。

    • 临时为查询结果添加一列以指定 CUBE 或 ROLLUP 操作是否添加行。使用 GROUPING 关键字。

    如下示例显示了选择列表中可能包含的许多项目:

    SELECT FirstName + ' ' + LastName AS "Employee Name", 
           IDENTITYCOL AS "Employee ID",
           HomePhone,
           Region,
           10 AS Constant
    FROM Northwind.dbo.Employees
    ORDER BY LastName, FirstName ASC
    

    选择所有列

    在 SELECT 语句中,星号 (*) 具有特殊的意义:

    • 当未使用限定符指定时,星号解析为对 FROM 子句中所指定的所有表或视图中的所有列的引用。如下示例检索 Shippers 表中的所有书籍信息:
      USE Northwind
      GO
      SELECT *
      FROM Shippers
      ORDER BY CompanyName
      GO
      
    • 当使用表或视图名称进行限定时,星号解析为对表或视图中的所有列的引用。如下示例使用星号来引用 Shippers 表中的所有列:
      USE Northwind
      GO
      SELECT Orders.OrderID, Shippers.*
      FROM Shippers
         JOIN
           Orders
         ON (Shippers.ShipperID = Orders.ShipVia)
      ORDER BY Orders.OrderID
      GO
     

    当使用 * 时,结果集中的列的顺序与 CREATE TABLE、ALTER TABLE 或 CREATE VIEW 语句中所指定的顺序相同。

    由于 SELECT * 会查找当前表中的所有列,因此每次执行 SELECT * 语句时,表结构的更改(添加、删除或重命名列)都会自动反映出来。

    如果在一个与结果集中的列数具有逻辑相关性的应用程序或脚本中使用 SELECT,最好在选择列表中指定所有列而不是指定一个星号。如果稍后在 SELECT 语句所引用的表或视图中添加了列,那么,当单独列出列时,应用程序将不会受更改的影响。如果指定了 *,则新的列成为结果集的一部分后可能影响应用程序或脚本的逻辑。

    如下示例首先检索 publishers 表中的所有列,然后按照 publishers 表最初创建时所定义的顺序显示这些列:

    USE Northwind
    GO
    SELECT *
    FROM [Order Details]
    ORDER BY OrderID ASC
    GO
    

    若要获得完全相同的结果,需要在 SELECT 语句之后按顺序显式列出表中所有列名:

    USE Northwind
    GO
    SELECT OrderID, ProductID, UnitPrice, Quantity, Discount
    FROM [Order Details]
    ORDER BY OrderID ASC
    GO
    

    说明  若要查找表的列名,则可使用 sp_help、SELECT column_name FROM INFORMATION_SCHEMA.

选择特定列

若要选择表中的特定列,则需在选择列表中明确地列出每一列。例如,若要仅列出作者的名字和他们的电话号码,可使用:

SELECT FirstName, HomePhone
FROM Northwind.dbo.Employees
ORDER BY FirstName ASC

在选择列表中,对列的指定还可包括指定别名(例如,proj_sales AS "Projected Sales")或其它表达式,例如 price = price * 1.15 或 SUM(SalesAmount)。

 

查询结果集中的常量

常量通常不作为单独的列在结果集中指定。对于应用程序本身而言,与要求服务器将常量值合并到跨网络返回的每一个结果集的行中相比,在显示结果时将常量值内置于结果中更为有效。

此常规规则的例外情况包括:

  • 存储过程可以由许多不同的应用程序或脚本调用。这些存储过程对应包含在结果中的常量值没有访问权限。过程本身中的 SELECT 语句随后应将常量指定为选择列表的一部分。

  • 当一个节点需要实施一个格式或显示标准时,该格式可内置于视图或存储过程中。

  • 当结果集已从服务器返回之后,某些脚本或工具不支持将常量合并到结果集中,而 SELECT 语句可能正好是从这样的脚本或工具执行的。

当字符列串联起来时,为了保证正确的格式和可读性,需要在其中包含字符串常量。如下示例将 LastNameFirstName 列合并成一列。在合并后的新列中,字符串 ', ' 将名称的两个部分分开,如下所示:

SELECT LastName + ', ' + FirstName AS EmployeeName
FROM Northwind.dbo.Employees
ORDER BY LastName, FirstName ASC

查询结果集中的常量

常量通常不作为单独的列在结果集中指定。对于应用程序本身而言,与要求服务器将常量值合并到跨网络返回的每一个结果集的行中相比,在显示结果时将常量值内置于结果中更为有效。

此常规规则的例外情况包括:

  • 存储过程可以由许多不同的应用程序或脚本调用。这些存储过程对应包含在结果中的常量值没有访问权限。过程本身中的 SELECT 语句随后应将常量指定为选择列表的一部分。

  • 当一个节点需要实施一个格式或显示标准时,该格式可内置于视图或存储过程中。

  • 当结果集已从服务器返回之后,某些脚本或工具不支持将常量合并到结果集中,而 SELECT 语句可能正好是从这样的脚本或工具执行的。

当字符列串联起来时,为了保证正确的格式和可读性,需要在其中包含字符串常量。如下示例将 LastNameFirstName 列合并成一列。在合并后的新列中,字符串 ', ' 将名称的两个部分分开,如下所示:

SELECT LastName + ', ' + FirstName AS EmployeeName
FROM Northwind.dbo.Employees
ORDER BY LastName, FirstName ASC

选择列表中的计算值

选择列表可包含通过对一个或多个简单表达式应用运算符而创建的表达式。这使结果集中得以包含基表中不存在,但是由存储在基表中的值计算而来的值。这些结果集列被称为导出列,并且包括:

  • 对数字列或常量使用算术运算符或函数进行的计算和运算:
    SELECT ROUND( (UnitPrice * .9), 2) AS DiscountPrice
    FROM Products
    WHERE ProductID = 58
    
  • 数据类型转换:
    SELECT ( CAST(ProductID AS VARCHAR(10)) + ': '
           + ProductName ) AS ProductIDName
    FROM Products
    
  • CASE 函数:
    SELECT ProductID, ProductName,
        CASE CategoryID
            WHEN 1 THEN ROUND( (UnitPrice * .6), 2)
            WHEN 2 THEN ROUND( (UnitPrice * .7), 2)
            WHEN 3 THEN ROUND( (UnitPrice * .8), 2)
            ELSE ROUND( (UnitPrice * .9), 2)
        END AS DiscountPrice
    FROM Products
    
  • 子查询:
    SELECT Prd.ProductID, Prd.ProductName,
           (   SELECT SUM(OD.UnitPrice * OD.Quantity)
               FROM Northwind.dbo.[Order Details] AS OD
               WHERE OD.ProductID = Prd.ProductID
           ) AS SumOfSales
    FROM Northwind.dbo.Products AS Prd
    ORDER BY Prd.ProductID
    

通过在带有算术运算符、函数、转换或嵌套查询的选择列表中使用数字列或数字常量,对数据进行计算和运算。算术运算符使您得以对数字数据进行加、减、乘和除运算。

支持下列算术运算符。

符号 操作
+
-
/
*
%

执行加、减、除和乘的算术运算符可用于任何数字列或表达式(intsmallinttinyintdecimalnumericfloatrealmoneysmallmoney)中。模运算符只能用于 int 列、smallint 列、tinyint 列或表达式中。

也可使用日期函数或常规加或减数学运算符对 datetime smalldatetime 列进行算术运算。

可使用算术运算符执行涉及一个或多个列的计算。在算术表达式中常量的使用是可选的,如下所示:

SELECT ProductID, ProductName,
       UnitPrice * UnitsInStock AS InventoryValue
FROM Northwind.dbo.Products

指定结果集的列名

AS 子句可用来更改结果集列名或为导出列指定名称。

当结果集列由对表或视图中的列的引用进行定义时,结果集列的名称与所引用列的名称相同。AS 子句可用于为结果集列指定不同的名称或别名。这样可增加可读性。例如:

SELECT EmpSSN AS "Employee Social Security Number"
FROM EmpTable

在选择列表中,有些列进行了具体指定,而不是简单的对列的引用,这些列便是导出列。除非使用 AS 子句指定了一个名称,否则导出列没有名称。在如下示例中,如果移去 AS 子句,那么使用 DATEDIFF 函数指定的导出列就没有名称:

SELECT OrderID,
       DATEDIFF(dd, ShippedDate, GETDATE() ) AS DaysSinceShipped
FROM Northwind.dbo.Orders
WHERE ShippedDate IS NOT NULL

AS 子句是在 SQL-92 标准中所定义的语法,用来为结果集列指派名称。下面是在 Microsoft® SQL Server™ 中首选的语法:

column_name AS column_alias

result_column_expression AS derived_column_name

Transact-SQL 为了兼容早期版本的 SQL Server,还支持下列语法:

column_alias = column_name

derived_column_name = result_column_expression

例如,上一个示例可用下列代码替换:

SELECT OrderID,
       DaysSinceShipped = DATEDIFF(dd, ShippedDate, GETDATE() )
FROM Northwind.dbo.Orders
WHERE ShippedDate IS NOT NULL

结果集列名的分隔

结果集列名是一个标识符。如果该名称是遵循标识符规则的常规标识符,那么就不需要分隔。如果该名称不遵循标识符规则,则必须使用方括号 ([]) 或双引号 (" ") 对其进行分隔。不论 QUOTED_IDENTIFIER 选项是如何设置的,都可使用双引号对结果集列名进行分隔。

说明  每个结果集的列名可最多使用 128 个字符。但是,DB-Library 应用程序(例如 isql 工具)在查询输出中最多将结果集列名截取为 30 个字符。SQL Server 6.5 或更低版本的 SQL Server ODBC 驱动程序也最多将结果集列名截取为 30 个字符。

 

如下示例在 publishers 表中根据 Book Publisher 列标题而不是默认的 pub_name 列标题检索出版商名称:

USE pubs
SELECT pub_name AS "Book Publisher"
FROM publishers
ORDER BY pub_name ASC

另外,Transact-SQL 的保留关键字可通过加引号而被用于列标题。例如,以下查询使用保留字 SUM 作为列标题:

USE pubs
SELECT SUM(ytd_sales) AS "sum"
FROM titles

Transact-SQL 还支持使用单引号 ('') 来分隔结果集列名。这可保持与 SQL Server 早期版本的兼容性,如下所示:

USE pubs
SELECT SUM(ytd_sales) AS 'sum'
FROM titles

使用 DISTINCT 消除重复项

DISTINCT 关键字可从 SELECT 语句的结果中除去重复的行。如果没有指定 DISTINCT,那么将返回所有行,包括重复的行。例如,如果在 titleauthor 中选择所有作者 ID 时未使用 DISTINCT,那么将会返回下列行(其中包括一些重复的行):

USE pubs
SELECT au_id
FROM titleauthor

下面是结果集:

au_id       
----------- 
172-32-1176 
213-46-8915 
213-46-8915 
238-95-7766 
267-41-2394 
267-41-2394 
274-80-9391 
409-56-7008 
427-17-2319 
472-27-2349 
486-29-1786 
486-29-1786 
648-92-1872 
672-71-3249 
712-45-1867 
722-51-5454 
724-80-9391 
724-80-9391 
756-30-7391 
807-91-6654 
846-92-7186 
899-46-2035 
899-46-2035 
998-72-3567 
998-72-3567 

(25 row(s) affected)

而使用了 DISTINCT 后,就能够除去重复项,而只查看唯一的作者 ID:

USE pubs
SELECT DISTINCT au_id
FROM titleauthor

下面是结果集:

au_id       
----------- 
172-32-1176 
213-46-8915 
238-95-7766 
267-41-2394 
274-80-9391 
409-56-7008 
427-17-2319 
472-27-2349 
486-29-1786 
648-92-1872 
672-71-3249 
712-45-1867 
722-51-5454 
724-80-9391 
756-30-7391 
807-91-6654 
846-92-7186 
899-46-2035 
998-72-3567 

(19 row(s) affected)

重要  涉及 DISTINCT 的语句的输出取决于列的排序规则或应用 DISTINCT 的表达式。有关不同排序规则的效果的更多信息,请参见 SQL Server 排序规则基础知识。

 

对于 DISTINCT 关键字来说,各空值将被认为是相互重复的内容。当 SELECT 语句中包括 DISTINCT 时,不论遇到多少个空值,在结果中只返回一个 NULL

说明  为了与 SQL-92 标准和其它的 Microsoft® SQL Server™ 版本兼容,ALL 关键字可以显式请求所有行。但是,由于 ALL 是默认的,所以无需指定它。

使用 TOP 和 PERCENT 限制结果集

TOP 子句限制返回到结果集中的行数。

TOP n [PERCENT]

n 指定返回的行数。如果未指定 PERCENT,n 就是返回的行数。如果指定了 PERCENT,n 就是返回的结果集行的百分比,如下所示:

TOP 120 /*Return the top 120 rows of the result set. */
TOP 15 PERCENT /* Return the top 15% of the result set. */.

如果一个 SELECT 语句既包含 TOP 又包含 ORDER BY 子句,那么返回的行将会从排序后的结果集中选择。整个结果集按照指定的顺序建立并且返回排好序的结果集的前 n 行。

限制结果集大小的另一种方法是在执行一个语句之前执行 SET ROWCOUNT n 语句。SET ROWCOUNT 与 TOP 的不同之处在于:

  • SET ROWCOUNT 限制适用对 ORDER BY 取值后在结果集中生成行。如果指定了 ORDER BY,SELECT 语句将在从某个已根据指定的 ORDER BY 分类进行了排序的值集中选择 n 行后终止。

  • TOP 子句适用于指定了该子句的单个 SELECT 语句。在执行另一个 SET ROWCOUNT 语句之前,SET ROWCOUNT 会一直有效,例如执行 SET ROWCOUNT 0 将会关闭此选项。
  • 使用 FROM 子句

    在每一条要从表或视图中检索数据的 SELCET 语句中,都需要使用 FROM 子句。用 FROM 子句可以:

    • 列出选择列表和 WHERE 子句中所引用的列所在的表和视图。可用 AS 子句为表和视图的名称指定别名。

    • 联接类型。这些类型由 ON 子句中指定的联接条件限定。

    FROM 子句是用逗号分隔的表名、视图名和 JOIN 子句的列表。

    Transact-SQL 具有扩展功能,可支持在 FROM 子句中指定除表或视图之外的其它对象。这些对象返回结果集,也就是 OLE DB 术语中所说的行集,该结果集构成了虚拟表。然后 SELECT 语句就像操作表一样操作这些结果集。

    FROM 子句可以指定:

    • 一个或多个表或视图。例如:
      SELECT *
      FROM Shippers
      
    • 两个表或视图之间的联接:
      SELECT Cst.CustomerID, Cst.CompanyName, Cst.ContactName,
             Ord.ShippedDate, Ord.Freight 
      FROM Northwind.dbo.Orders AS Ord
        JOIN
           Northwind.dbo.Customers AS Cst
        ON (Cst.CustomerID = Ord.CustomerID)
      
    • 一个或多个派生表,这些派生表是 FROM 子句中的 SELECT 语句,以别名或用户指定的名称来引用这些派生表。FROM 子句中 SELECT 语句的结果集构成了外层 SELECT 语句所用的表。例如,下面的 SELECT 语句使用派生表查找是否有哪家书店备有 pubs 数据库中所有种类的书籍:
      SELECT ST.stor_id, ST.stor_name
      FROM stores AS ST,
           (SELECT stor_id, COUNT(DISTINCT title_id) AS title_count
            FROM sales
            GROUP BY stor_id
           ) AS SA
      WHERE ST.stor_id = SA.stor_id
        AND SA.title_count = (SELECT COUNT(*) FROM titles)
      
    • sp_addlinkedserver 定义的链接服务器中的一个或多个表或视图。链接服务器可以是任何 OLE DB 数据源。

    • 用 OPENROWSET 或 OPENQUERY 函数返回的 OLE DB 行集。

    Microsoft® SQL Server™ 2000 分布式查询的基础是链接服务器、OPENROWSET 和 OPENQUERY。它们提供了在 Transact-SQL 语句中查询或修改任意 OLE DB 数据源中数据的能力。

    没有 FROM 子句的 SELECT 语句

    不需要 FROM 子句的 SELECT 语句是那些不从数据库内的任何表中选择数据的 SELECT 语句。这些 SELECT 语句只从局部变量或不对列进行操作的 Transact-SQL 函数中选择数据,例如:

    SELECT @MyIntVariable
    SELECT @@VERSION
    SELECT DB_ID('Northwind')
    

    使用表别名

    SELECT 语句的可读性可通过为表指定别名来提高,别名也称为相关名称或范围变量。指派表的别名时,可以使用也可以不使用 AS 关键字:

    • table_name AS table alias

    • table_name table_alias

    在下例中,为 publishers 指派了别名 p

    USE pubs
    SELECT p.pub_id, p.pub_name
    FROM publishers AS p
    

    如果为表指派了别名,那么在该 Transact-SQL 语句中对该表的所有显式引用都必须使用别名,而不能使用表名。例如,下列 SELECT 语句将产生语法错误,因为该语句在已指派别名的情况下又使用了表名:

    SELECT Customers.CustomerID, /* Illegal reference to Customers. */
           Cst.FirstName, Cst.LastName
    FROM Northwind.dbo.Customers AS Cst
    

    用 WHERE 和 HAVING 筛选行

    SELECT 语句中的 WHERE 和 HAVING 子句控制用源表中的那些行来构造结果集。WHERE 和 HAVING 是筛选。这两个子句指定指定一系列搜索条件,只有那些满足搜索条件的行才用来构造结果集。我们称满足搜索条件的行符合参与行集的限定条件。例如,下列 SELECT 语句中的 WHERE 子句将限定只选择地区为华盛顿州 (WA) 的行:

    SELECT CustomerID, CompanyName
    FROM Northwind.dbo.Customers
    WHERE Region = 'WA'
    

    HAVING 子句通常与 GROUP BY 子句结合使用,尽管指定该子句时也可以不带 GROUP BY。HAVING 子句指定在应用 WHERE 子句的筛选后要进一步应用的筛选。例如,下列 WHERE 子句仅限定以高于 $100 的单价销售产品的订单,而 HAVING 子句进一步将结果限制为只包括 100 件以上的订单:

    SELECT OrdD1.OrderID AS OrderID,
           SUM(OrdD1.Quantity) AS "Units Sold",
           SUM(OrdD1.UnitPrice * OrdD1.Quantity) AS Revenue
    FROM [Order Details] AS OrdD1
    WHERE OrdD1.OrderID in (SELECT DISTINCT OrdD2.OrderID
                            FROM [Order Details] AS OrdD2
                            WHERE OrdD2.UnitPrice > $100)
    GROUP BY OrdD1.OrderID
    HAVING SUM(OrdD1.Quantity) > 100
    

    WHERE 和 HAVING 子句中的搜索条件或限定条件可包括:

    • 比较运算符(如 =、< >、< 和 >)。例如,下列查询从 Products 表中检索产品分类为 2 的行:
      SELECT ProductID, ProductName
      FROM Northwind.dbo.Products
      WHERE CategoryID = 2
      ORDER BY ProductID
      
    • 范围(BETWEEN 和 NOT BETWEEN)。例如,下列查询从 Products 表中检索产品分类从 2 到 4 的行:
      SELECT CategoryID, ProductID, ProductName
      FROM Northwind.dbo.Products
      WHERE CategoryID BETWEEN 2 and 4
      ORDER BY CategoryID, ProductID
      
    • 列表(IN、NOT IN)。例如,下列查询从 Products 表中检索产品分类 ID 与列表中某一 ID 匹配的行:
      SELECT CategoryID, ProductID, ProductName
      FROM Northwind.dbo.Products
      WHERE CategoryID IN (1,4,5,7)
      ORDER BY CategoryID, ProductID
      
    • 模式匹配(LIKE 和 NOT LIKE)。例如,下列查询从 Products 表中检索产品名称以 Ch 开头的行:
      SELECT CategoryID, ProductID, ProductName
      FROM Northwind.dbo.Products
      WHERE ProductName LIKE 'Ch%'
      ORDER BY CategoryID, ProductID
      

      说明  可用于 text 列的 WHERE 条件只有返回其它数据类型的函数(如 PATINDEX())或运算符(如 IS NULL、IS NOT NULL、LIKE 和 NOT LIKE)。

    • 空值(IS NULL 和 IS NOT NULL)。例如,下列查询从 Customers 表中检索客户地区不为 NULL 的行:
      SELECT CompanyName, City, Region, Country
      FROM Northwind.dbo.Customers
      WHERE Region IS NOT NULL
      ORDER BY CompanyName
      

      说明  比较空值时请谨慎从事。例如,指定 = NULL 与指定 IS NULL 是不同的。有关更多信息,请参见空值。

    • 所有记录(=ALL、>ALL、<= ALL、ANY)。例如,下列查询从 Order Details 表中检索装运产品数量大于分类 1 中任意产品的装运数量的订单和产品 ID:
      USE Northwind
      GO
      SELECT OrdD1.OrderID, OrdD1.ProductID
      FROM "Order Details" OrdD1
      WHERE OrdD1.Quantity > ALL
            (SELECT OrdD2.Quantity
             FROM "Order Details" OrdD2 JOIN Products Prd
                   ON OrdD2.ProductID = Prd.ProductID
             WHERE Prd.CategoryID = 1)
      GO
      
    • 上述条件的组合(AND、OR、NOT)。例如,下列查询检索库存水平低于再订购点,或来自供应商 15 并属于分类 4 的所有产品:
      SELECT ProductID, ProductName
      FROM Northwind.dbo.Products
      WHERE UnitsInStock < ReorderLevel
         OR (SupplierID = 15 AND CategoryID = 4)
      

    说明  当在 WHERE 子句中搜索 Unicode 字符串时,请在搜索字符串之前加字符 N,例如:

    SELECT CompanyName, ContactName, Phone, Fax
    FROM Northwind.dbo.Customers
    WHERE CompanyName = N'Berglunds snabbköp'
    

你可能感兴趣的:(sql,server,服务器,Microsoft,table,null,sqlserver)