SELECT (Transact-SQL)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse AnalyticsAnalytics Platform System (PDW)Microsoft Fabric 中的 SQL 分析终结点Microsoft Fabric 中的仓库

从数据库中检索行,并允许从 SQL Server 中的一个或多个表中选择一个或多个行或列。 虽然 SELECT 语句的完整语法较复杂,但其主要子句可归纳如下:

[ WITH { [ XMLNAMESPACES ,][ <common_table_expression> ] } ]

SELECT select_list [ INTO new_table ]

[ FROM table_source ] [ WHERE search_condition ]

[ GROUP BY group_by_expression ]

[ HAVING search_condition ]

[ WINDOW 窗口表达式]

[ ORDER BY order_expression [ ASC | DESC ]]

可在查询之间使用 UNIONEXCEPT 和 INTERSECT 运算符,以便将各个查询的结果合并到一个结果集中或进行比较。

Transact-SQL 语法约定

语法

-- Syntax for SQL Server and Azure SQL Database  
  
<SELECT statement> ::=    
    [ WITH { [ XMLNAMESPACES ,] [ <common_table_expression> [,...n] ] } ]  
    <query_expression>   
    [ ORDER BY <order_by_expression> ] 
    [ <FOR Clause>]   
    [ OPTION ( <query_hint> [ ,...n ] ) ]   
<query_expression> ::=   
    { <query_specification> | ( <query_expression> ) }   
    [  { UNION [ ALL ] | EXCEPT | INTERSECT }  
        <query_specification> | ( <query_expression> ) [...n ] ]   
<query_specification> ::=   
SELECT [ ALL | DISTINCT ]   
    [TOP ( expression ) [PERCENT] [ WITH TIES ] ]   
    < select_list >   
    [ INTO new_table ]   
    [ FROM { <table_source> } [ ,...n ] ]   
    [ WHERE <search_condition> ]   
    [ <GROUP BY> ]   
    [ HAVING < search_condition > ]   
-- Syntax for Azure Synapse Analytics and Parallel Data Warehouse  
  
[ WITH <common_table_expression> [ ,...n ] ]  
SELECT <select_criteria>  
[;]  
  
<select_criteria> ::=  
    [ TOP ( top_expression ) ]   
    [ ALL | DISTINCT ]   
    { * | column_name | expression } [ ,...n ]   
    [ FROM { table_source } [ ,...n ] ]  
    [ WHERE <search_condition> ]   
    [ GROUP BY <group_by_clause> ]   
    [ HAVING <search_condition> ]   
    [ ORDER BY <order_by_expression> ]  
    [ OPTION ( <query_option> [ ,...n ] ) ]  
  

注意

若要查看 SQL Server 2014 (12.x) 及更早版本的 Transact-SQL 语法,请参阅早期版本文档

备注

由于 SELECT 语句的复杂性,下面按子句说明详细的语法元素和参数:

SELECT 语句中的子句顺序非常重要。 可以省略可选子句,但这些子句在使用时必须按适当的顺序出现。

只有当这些语句的选择列表包含给函数的局部变量赋值的表达式时,在用户定义函数中才允许有 SELECT 语句。

对于由四部分组成的名称,若其中的服务器名称使用的是 OPENDATASOURCE 函数,则该名称可以在表名能够在 SELECT 语句内出现的任何位置作为表源使用。 无法为 Azure SQL 数据库 指定由四部分组成的名称。

某些应用于 SELECT 语句的语法限制涉及到远程表。

SELECT 语句的逻辑处理顺序

以下步骤显示 SELECT 语句的逻辑处理顺序(即绑定顺序)。 此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句。 例如,如果查询处理器可以绑定到(访问)在 FROM 子句中定义的表或视图,则这些对象及其列可用于所有后续步骤。 相反,因为 SELECT 子句处于步骤 8,所以,在该子句中定义的任何列别名或派生列都无法被之前的子句引用。 不过,它们可由 ORDER BY 子句之类的后续子句引用。 该语句的实际物理执行由查询处理器确定,因此顺序可能与此列表不同。

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE 或 WITH ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

警告

上述顺序是常规顺序。 但是仍然存在不同于此顺序的少见情况。

例如,假设视图中具有聚集索引,该视图排除了一些表行,并且视图的 SELECT 列列表使用可将数据类型从 varchar 更改为 integer 的 CONVERT 。 在此情况下,CONVERT 可能会先于 WHERE 语句执行。 这种情况确实少见。 如果需要解决此问题,通常可通过某种方法修改视图来避免出现顺序不同的情况。

权限

选择数据要求对表或视图具有 SELECT 权限,该权限可从更高级别的权限继承,例如针对架构的 SELECT 权限或针对表的 CONTROL 权限。 或者要求具有 db_datareader 或 db_owner 固定数据库角色或 sysadmin 固定服务器角色的成员身份 。 使用 SELECT INTO 创建新表既要求 CREATE TABLE 权限,还要求拥有新表的架构上的 ALTER SCHEMA 权限 。

示例:

以下示例使用 AdventureWorksPDW2022 数据库。

A. 使用 SELECT 检索行和列

本部分演示三个代码示例。 此第一个代码示例返回 DimEmployee 表中的所有行(未指定 WHERE 子句)和所有列(使用了 *)。

SELECT *  
FROM DimEmployee  
ORDER BY LastName;  

此第二个示例使用表别名实现相同结果。

SELECT e.*  
FROM DimEmployee AS e  
ORDER BY LastName;  

此示例返回 AdventureWorksPDW2012 数据库的 DimEmployee 表中的所有行(未指定 WHERE 子句)以及列(FirstNameLastNameStartDate)的子集。 第三个列标题重命名为 FirstDay

SELECT FirstName, LastName, StartDate AS FirstDay  
FROM DimEmployee   
ORDER BY LastName;  

此示例仅返回 DimEmployee 的行,其中包含非 NULL 的 EndDate 和为“M”(已婚)的 MaritalStatus

SELECT FirstName, LastName, StartDate AS FirstDay  
FROM DimEmployee   
WHERE EndDate IS NOT NULL   
AND MaritalStatus = 'M'  
ORDER BY LastName;  

B. 将 SELECT 与列标题和列计算一起使用

下面的示例返回 DimEmployee 表中的所有行,并基于每位员工的 BaseRate 和 40 小时工作周计算他们的总工资。

SELECT FirstName, LastName, BaseRate, BaseRate * 40 AS GrossPay  
FROM DimEmployee  
ORDER BY LastName;  

C. 将 DISTINCT 与 SELECT 一起使用

下面的示例使用 DISTINCTDimEmployee 表中的所有唯一标题生成列表。

SELECT DISTINCT Title  
FROM DimEmployee  
ORDER BY Title;  

D. 使用 GROUP BY

下面的示例查找每天所有销售的总金额。

SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales  
FROM FactInternetSales  
GROUP BY OrderDateKey  
ORDER BY OrderDateKey;  

由于使用了 GROUP BY 子句,因此每天只返回一行销售总额。

E. 对多个组使用 GROUP BY

下面的示例查找平均价格和每天的互联网销售总额(按订单日期和促销关键字进行分组)。


SELECT OrderDateKey, PromotionKey, AVG(SalesAmount) AS AvgSales, SUM(SalesAmount) AS TotalSales  
FROM FactInternetSales  
GROUP BY OrderDateKey, PromotionKey  
ORDER BY OrderDateKey;   

F. 使用 GROUP BY 和 WHERE

下面的示例在只检索订单日期晚于 2002 年 8 月 1 日的行后对结果进行分组。

SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales  
FROM FactInternetSales  
WHERE OrderDateKey > '20020801'  
GROUP BY OrderDateKey  
ORDER BY OrderDateKey;  

G. 将 GROUP BY 与表达式一起使用

以下示例按表达式进行分组。 如果表达式不包含聚合函数,则可以按表达式进行分组。

SELECT SUM(SalesAmount) AS TotalSales  
FROM FactInternetSales  
GROUP BY (OrderDateKey * 10);  

H. 将 GROUP BY 与 ORDER BY 一起使用

下面的示例查找每天的总销售额以及当天的订单。

SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales  
FROM FactInternetSales  
GROUP BY OrderDateKey  
ORDER BY OrderDateKey;  

I. 使用 HAVING 子句

此查询使用 HAVING 子句限制结果。

SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales  
FROM FactInternetSales  
GROUP BY OrderDateKey  
HAVING OrderDateKey > 20010000  
ORDER BY OrderDateKey;  

另请参阅

SELECT 示例 (Transact-SQL)
提示 (Transact-SQL)