Access SQL 简介
如果要在数据库中检索数据,可以使用结构化查询语言,即 SQL。SQL 是一种近似英语的计算机语言,但数据库程序可以理解这种语言。您运行的每个查询都在后台使用 SQL。
了解 SQL 的工作原理可以帮助您创建更好的查询,并使您更容易理解如何修复一个不返回所需结果的查询。
注释 不可编辑 Web 查询的 SQL。
本文内容
SQL 是一种用于处理多组事实和事实之间关系的计算机语言。Microsoft Office Access 等关系数据库程序使用 SQL 来处理数据。SQL 和许多计算机语言不同的是,即使对于初学者也不难阅读和理解。SQL 和许多计算机语言相同的是,它作为一种国际标准得到标准化机构(如 ISO(英文) 和 ANSI(英文))的认可。
SQL 即使对于初学者也不难阅读和理解。 |
可以使用 SQL 描述有助于您回答问题的多组数据。使用 SQL 时,必须使用正确语法。语法是一组规则,按这组规则将语言元素正确地组合起来。SQL 语法以英语语法为基础,使用的许多元素与 VISUAL BASIC FOR APPLICATIONS (VBA) (VISUAL BASIC FOR APPLICATIONS (VBA):MICROSOFT VISUAL BASIC 的宏语言版本,用于编写基于 MICROSOFT WINDOWS 的应用程序,内置于多个 MICROSOFT 程序中。) 语法相同。
例如,一个简单的 SQL 语句如下,该语句用于检索姓氏列表中名字是“Mary”的联系人:
SELECT Last_Name
FROM Contacts
WHERE First_Name = 'Mary';
注释 SQL 不仅用于操纵数据,而且用于创建和更改数据库对象(如表)的设计。用于创建和更改数据库对象的那部分 SQL 叫做数据定义语言 (DDL)。本主题不涉及 DDL。有关详细信息,请参阅使用数据定义查询创建或修改表或索引一文。
要使用 SQL 描述一组数据,您可以编写 SELECT 语句。一个 SELECT 语句包含您要从数据库中获得的一组数据的完整描述, 其中包括:
✍ | 哪些表包含数据。 |
✍ | 不同数据源中的数据怎样关联。 |
✍ | 哪些字段或计算将产生数据。 |
✍ | 数据必须符合哪些条件才能被选中。 |
✍ | 是否以及怎样对结果进行排序。 |
SQL 语句和句子一样有子句。每个子句执行一个 SQL 语句的功能。某些子句在 SELECT 语句中是必需的。下表列出了最常见的 SQL 子句。
SQL 子句 |
执行的操作 |
是否必需 |
SELECT |
列出含有关注的数据的字段。 |
是 |
FROM |
列出的表中含有 SELECT 子句中列出的字段。 |
是 |
WHERE |
指定要包括在结果内的每条记录必须符合的字段条件。 |
否 |
ORDER BY |
指定怎样对结果进行排序。 |
否 |
GROUP BY |
在包含聚合函数的 SQL 语句中,列出未在 SELECT 子句中汇总的字段。 |
仅在存在这类字段时才是必需的 |
HAVING |
在包含聚合函数的 SQL 语句中,指定应用于在 SELECT 语句中汇总的字段的条件。 |
否 |
每个 SQL 子句都由相当于词类的词条组成。下表列出了 SQL 词条类型。
SQL 词条 |
相当的词类 |
定义 |
示例 |
标识符 |
名词 |
用来标识数据库对象的名称,如字段名称。 |
客户.[电话号码] |
运算符 |
动词或副词 |
表示操作或修改操作的关键字。 |
AS |
常量 |
名词 |
不发生更改的值,如数字或 NULL。 |
42 |
表达式 |
形容词 |
标识符、运算符、常量和函数的组合,可计算为单个值。 |
>= 产品.[单价] |
SQL 语句采用以下一般形式:
SELECT field_1
FROM table_1
WHERE criterion_1
;
注释
✍ | Access 会忽略 SQL 语句中的换行符。不过,对于您自己和其他人,考虑让每个子句使用一行有助于提高 SQL 语句的可读性。 |
✍ | 每个 SELECT 语句都以分号 (;) 结束。分号可以出现在最后一个子句的末尾或者单独出现在 SQL 语句末尾处的一行。 |
下面的内容演示了在 Access 中用于简单选择查询的 SQL 语句的外观:
SELECT 子句
FROM 子句
WHERE 子句
此示例 SQL 语句可以读作“选择存储在名为‘联系人’的表内名为‘电子邮件地址’和‘公司’的字段中的数据,特别是‘城市’字段的值为‘西安’的记录。”
我们来看一下该示例,一次看一个子句,以便了解 SQL 语法如何工作。
SELECT [电子邮件地址], 公司
这是 SELECT 子句。它由一个运算符 (SELECT) 及后面的两个标识符([电子邮件地址] 和“公司”)组成。
如果标识符中包含空格或特殊字符(如“电子邮件地址”),则必须用方括号将它括起来。
SELECT 子句不必指出包含字段的表,并且它无法指定要包括的数据必须满足的任何条件。
在 SELECT 语句中,SELECT 子句始终出现在 FROM 子句的前面。
FROM 联系人
这是 FROM 子句。它由一个运算符 (FROM) 及后面的标识符(联系人)组成。
FROM 子句不会列出要选择的字段。
WHERE 城市="西安"
这是 WHERE 子句。它由一个运算符 (WHERE) 及后面的表达式(城市="西安") 组成。
注释 与 SELECT 和 FROM 子句不同,WHERE 子句不是 SELECT 语句的必需元素。
通过使用 SELECT、FROM 和 WHERE 子句,您可以完成 SQL 支持的许多操作。有关如何使用这些子句的详细信息将在本文末尾的以下节中另行提供:
与 Microsoft Office Excel 一样,Access 允许您对数据表中的查询结果排序。还可以使用 ORDER BY 子句在查询中指定当查询运行时您所希望的结果排序方式。如果使用 ORDER BY 子句,则该子句是 SQL 语句中的最后一个子句。
ORDER BY 子句包含要用于排序的字段的列表,字段的顺序与要应用的排序操作中的顺序相同。
例如,假定您希望首先按照“公司”字段的值以降序对结果排序,并且如果存在值与“公司”的值相同的记录,再按照“电子邮件地址”字段中的值以升序排序。您的 ORDER BY 子句将类似于以下内容:
ORDER BY 公司 DESC, [电子邮件地址]
注释 默认情况下,Access 会按照升序(A-Z,从最小到最大)对值排序。而使用 DESC 关键字可以按照降序对值排序。
有关 ORDER BY 子句的详细信息,请参阅 ORDER BY 子句这一主题。
有时候您想要处理汇总数据,例如一个月的总销售额或者库存中最昂贵的物品。为此,您向 SELECT 子句中的字段应用了聚合函数 (聚合函数:用于计算总计的函数。例如:SUM、COUNT、AVG 或 VAR。)。例如,如果您希望查询显示为每家公司列出的电子邮件地址计数,则 SELECT 子句可能类似于以下内容:
SELECT COUNT([电子邮件地址]), 公司
可以使用的聚合函数取决于要使用的字段或表达式中的数据类型。有关可用的聚合函数的详细信息,请参阅 SQL 聚合函数一文。
在使用聚合函数时,通常还必须创建一个 GROUP BY 子句。GROUP BY 子句列出未应用聚合函数的所有字段。如果您向查询中的所有字段应用了聚合函数,则不必创建 GROUP BY 子句。
GROUP BY 子句紧跟在 WHERE 子句或 FROM 子句(如果没有 WHERE 子句)后面。GROUP BY 子句会像字段在 SELECT 子句中出现的那样列出字段。
例如,继续使用上一个示例,如果 SELECT 子句向 [电子邮件地址] 而未向“公司”应用聚合函数,则 GROUP BY 子句将类似于以下内容:
GROUP BY 公司
有关 GROUP BY 子句的详细信息,请参阅 GROUP BY 子句这一主题。
如果要使用条件来限制结果,但要应用条件的字段用在聚合函数中,则您无法使用 WHERE 子句。可以使用 HAVING 子句。HAVING 子句的工作方式类似于 WHERE 子句,但是它用于聚合数据。
例如,假定您将 AVG 函数(计算平均值)用于 SELECT 子句中的第一个字段:
SELECT COUNT([电子邮件地址]), 公司
如果您希望查询基于 COUNT 函数的值来限制结果,则您不能在 WHERE 子句中将条件用于该字段。不过,可以将条件放在 HAVING 子句中。例如,如果您只想让查询在有多个电子邮件地址与公司关联时返回行,则 HAVING 子句可能类似于以下内容:
HAVING COUNT([电子邮件地址])>1
注释 查询可以有一个 WHERE 子句和一个 HAVING 子句,未在聚合函数中使用的字段的条件进入 WHERE 子句,而用于聚合函数的字段的条件进入 HAVING 子句。
有关 HAVING 子句的详细信息,请参阅 HAVING 子句这一主题。
当您希望将几个相似的选择查询返回的所有数据一起作为一个合并的集合查看时,便可以使用 UNION 运算符。
UNION 运算符让您将两个 SELECT 语句合二为一。合并的 SELECT 语句必须具有相同的输出字段数、采用相同的顺序并包含相同或兼容的数据类型。在运行查询时,来自每组相应字段的数据将合并到一个输出字段中,这样查询输出所包含的字段数将与每个 Select 语句相同。
注释 根据联合查询的目的,“数字”和“文本”数据类型兼容。
使用 UNION 运算符时,还可以通过使用 ALL 关键字指定查询结果是否应包含重复行(如果存在)。
对于合并了两个 SELECT 语句的联合查询,其基本 SQL 语法如下:
SELECT field_1
FROM table_1
UNION [ALL]
SELECT field_a
FROM table_a
;
例如,假设您有两个表,分别名为“产品”和“服务”。这两个表都具有包含下列内容的字段:产品或服务的名称、价格、保修或担保条款以及是否以独占方式提供产品或服务。虽然“产品”表存储了保修信息,而“服务”表存储了担保信息,但基本信息是相同的(即特定的产品或服务是否包括质量承诺)。您可以使用下面这样的联合查询将这两个表中的四个字段合并在一起:
SELECT name, price, warranty_available, exclusive_offer
FROM Products
UNION ALL
SELECT name, price, guarantee_available, exclusive_offer
FROM Services
;
有关如何使用 UNION 运算符合并 SELECT 语句的详细信息,请参阅使用联合查询合并多个选择查询的结果一文。
在 SELECT 语句中,SELECT 子句列出了包含要使用的数据的字段。
在 SELECT 子句中,可以使用方括号字段名称括起来。如果名称中没有包含任何空格或特殊字符(如标点符号),则方括号是可选的。如果名称中确实包含空格或特殊字符,则必须使用方括号。
提示 包含空格的名称可读性更好并且在您设计窗体和报表时可以节省时间,但也会让您在编写 SQL 语句时的键入工作量增大。在数据库中命名对象时您应该考虑这个情况。
如果 SQL 语句中有两个或更多个同名字段,则必须将每个字段的数据源名称添加到 SELECT 子句内的字段名称中。用于数据源的名称与您在 FROM 子句中使用的名称相同。
在您想要包括数据源中的所有字段时,可以在 SELECT 子句中逐一列出所有字段,也可以使用星号通配符 (*)。使用星号时,Access 会在查询运行时确定数据源中包含哪些字段,并在查询中包括所有这些字段。这有助于确保在向数据源添加新字段时查询始终都是最新的。
可以在 SQL 语句中将星号用于一个或多个数据源。如果使用星号并且有多个数据源,则必须将数据源名称与星号一同包括,以便 Access 可以确定要包括哪个数据源中的所有字段。
例如,假定您要在 Orders 表中选择所有字段但在联系人表中仅选择电子邮件地址, 则 SELECT 子句可能类似于:
SELECT Orders.*, 联系人.[电子邮件地址]
注释 记录使用星号的时间。如果新字段是后来添加到数据源中的并且您没有对它们进行规划,则查询结果可能不会如您所愿。
如果您知道您的语句将选择重复的数据,而且您只想看到不同的值,则可以在 SELECT 子句中使用 DISTINCT 关键字。例如,假定您的每位客户都代表着一些不同的利益集团,其中一些使用相同的电话号码。如果您想确保每个电话号码只显示一次,则 SELECT 子句如下所示:
SELECT DISTINCT [txtCustomerPhone]
可以通过在 SELECT 子句中使用 AS 关键字和字段别名来更改为数据表视图中的任何字段显示的标签。字段别名是您为了使结果的可读性更强而分配给查询中的字段的名称。例如,如果要从名为 txtCustPhone 的字段中选择数据,并且该字段包含客户电话号码,则可以通过在 SELECT 语句中使用字段别名来提高结果的可读性,如下所示:
SELECT [txtCustPhone] AS [客户电话号码]
注释 在 SELECT 子句中使用表达式时必须使用字段别名。
有时候您想查看基于您的数据的计算结果,或者仅检索字段的一部分数据。例如,假定您要基于数据库中出生日期字段中的数据返回客户的出生年份。您的 SELECT 子句可能类似于以下内容:
SELECT DatePart("yyyy",[出生日期]) AS [出生年份]
此表达式包括 DATEPART 函数和两个参数:“yyyy”(一个常量)和 [出生日期](一个标识符)。
可以使用任何一个有效表达式作为字段,条件是在给定单个输入值时该表达式输出单个值。
在 SELECT 语句中,FROM 子句指定包含 SELECT 子句将要使用的数据的表或查询。
假定您想知道某个特定客户的电话号码。假设包含存储此数据的字段的表名为 tblCustomer,FROM 子句将类似于以下内容:
FROM tblCustomer
可以使用方括号将名称括起来。如果名称中没有包含任何空格或特殊字符(如标点符号),则方括号是可选的。如果名称中确实包含空格或特殊字符,则必须使用方括号。
提示 包含空格的名称可读性更好并且在您设计窗体和报表时可以节省时间,但也会让您在编写 SQL 语句时的键入工作量增大。在数据库中命名对象时您应该考虑这个情况。
通过在 FROM 子句中使用表别名,可以在 SELECT 语句中用不同的名称来引用数据源。表别名是一个名称,当您将表达式作为数据源或者要使 SQL 语句更容易键入和阅读时可以在查询中将该名称分配给数据源。如果数据源名称过长或者难于键入,尤其是多个字段在不同的表中具有相同名称时,表别名特别有用。
例如,如果想从两个名称均为 ID 的字段中选择数据,并且其中一个字段在表 tblCustomer 中,另一个在表 tblOrder 中,则 SELECT 子句可能类似于以下内容:
SELECT [tblCustomer].[ID], [tblOrder].[ID]
通过在 FROM 子句中使用表别名,可以使查询更容易键入。包含表别名的 FROM 子句可能类似于以下内容:
FROM [tblCustomer] AS [C], [tblOrder] AS [O]
然后,您可以在 SELECT 子句中使用这些表别名,如下所示:
SELECT [C].[ID], [O].[ID]
注释 使用表别名时,可以通过使用数据源的别名或者完整名称在 SQL 语句中引用数据源。
如果您需要一种方法将两个数据源中的记录对合并为查询结果中的单个记录,可以执行联接。联接是一种 SQL 操作,它指定如何将两个数据源关联,以及在一个数据源中没有对应数据时是否应包括另一个数据源中的数据。
要合并两个数据源中的信息,可以对两个数据源中的公共字段执行联接操作。当此字段中存储的值匹配时,记录中的数据将合并到结果内。
除了合并数据外,还可以使用联接指定在相关表中没有对应记录时是否包括任何一个表中的记录。
例如,假定您要在查询中使用以下两个表中的数据:tblCustomer 和 tblOrder。这两个表都有一个用来标识客户的 CustomerID 字段。tblCustomer 表中的每条记录在 tblOrder 表中可能有一条或更多条对应的记录,并且对应值可由 CustomerID 字段中的值决定。
如果想要联接表以使查询合并表中的记录并在一个表中没有对应记录时排除任何一个表中的记录,则 FROM 子句可能类似于以下内容(此处增加的换行符是为了提高可读性):
FROM [tblCustomer] INNER JOIN [tblOrder]
ON [tblCustomer].[CustomerID]=[tblOrder].[CustomerID]
在 Microsoft Office Access 中,联接在 SELECT 语句的 FROM 子句中进行。联接有两种类型:内部联接和外部联接。以下部分将介绍这两种类型的联接。
内部联接是最常见的联接类型。在包含内部联接的查询运行时,查询结果中只包含两个联接表中存在有公共值的记录。
内部联接的语法如下(此处增加的换行符是为了提高可读性):
FROM table1 INNER JOIN table2
ON table1.field1 compopr table2.field2
下表介绍 INNER JOIN 操作的不同部分。
部分 |
说明 |
table1、table2 |
要合并其中的记录的表的名称。 |
field1,field2 |
要联接的字段的名称。如果它们不是数值,则字段必须属于相同的数据类型 (数据类型:决定字段可拥有的数据类型的字段特征。数据类型包括 BOOLEAN、INTEGER、LONG、CURRENCY、SINGLE、DOUBLE、DATE、STRING 和 VARIANT(默认)。),并且包含相同种类的数据,但它们不必有相同的名称。 |
compopr |
任何关系比较运算符:“=”、“<”、“>”、“<=”、“>=”或“<>”。 |
外部联接与内部联接类似,因为它们都指示查询如何去合并两个源中的信息。它们又是不同的,因为它们还指定不存在公共值时是否包括数据。外部联接具有方向性:可以指定是包括在联接中指定的第一个数据源中的所有记录(称为左联接),还是包括联接中第二个数据源中的所有记录(称为右联接)。
外部联接的语法如下:
FROM table1 [ LEFT | RIGHT ] JOIN table2
ON table1.field1compopr table2.field2
下表介绍 LEFT JOIN 和 RIGHT JOIN 操作的不同部分。
部分 |
说明 |
table1、table2 |
要合并其中的记录的表的名称。 |
field1,field2 |
要联接的字段的名称。字段必须为相同数据类型 (数据类型:决定字段可拥有的数据类型的字段特征。数据类型包括 BOOLEAN、INTEGER、LONG、CURRENCY、SINGLE、DOUBLE、DATE、STRING 和 VARIANT(默认)。)并且包含相同类型的数据,但不必具有相同名称。 |
compopr |
任何关系比较运算符:“=”、“<”、“>”、“<=”、“>=”或“<>”。 |
有关联接的详细信息,请参阅联接表和查询一文。
当您想使用数据来限制查询中返回的记录数时,可以使用 SELECT 语句的 WHERE 子句中的查询条件 (条件:所指定的限制查询或筛选的结果集中包含哪些记录的条件。)。查询条件类似于公式,它是一个可能由字段引用、运算符 (运算符:一个标记或符号,指定表达式内执行的计算的类型。有数学、比较、逻辑和引用运算符等。)及常量 (常量:不进行计算的值,因此也不会发生变化。例如,数字 210 以及文本“每季度收入”都是常量。表达式以及表达式产生的值都不是常量。)组成的字符串。查询条件属于表达式 (表达式:算术或逻辑运算符、常数、函数和字段名称、控件和属性的任意组合,计算结果为单个值。表达式可执行计算、操作字符或测试数据。)类型。
下表显示了一些示例条件并介绍了它们的工作原理。
条件 |
说明 |
>25 and <50 |
此条件适用于数字字段,如“Price”或“UnitsInStock”。该条件只包括其字段中的值大于 25 并且小于 50 的那些记录。 |
DateDiff ("yyyy", [出生日期], Date()) > 30 |
此条件适用于日期/时间字段,如“出生日期”。查询结果中只包括人员出生日期与当前日期之间的年数大于 30 的记录。 |
Is Null |
此条件可应用于任何类型的字段,以显示字段值为空的记录。 |
如上表所示,条件相互之间看上去可能会存在很大的差异,具体取决于条件要应用到的字段的数据类型以及您的具体要求。一些条件较为简单,它们使用基本运算符和常量。其他条件则较为复杂,它们使用函数和特殊运算符并且包含字段引用。
要点 如果将字段用于聚合函数,则不能在 WHERE 子句中为该字段指定条件。相反,可以使用 HAVING 子句为聚合字段指定条件。有关详细信息,请参阅处理汇总数据:GROUP BY 和 HAVING一节。
WHERE 子句的基本语法如下:
WHERE field = criterion
例如,假定您需要某个客户的电话号码,但您只记得该客户的姓氏是黎。您可以使用 WHERE 子句限制结果并使得查找所需的电话号码更为容易,而不是查看数据库中的所有电话号码。假定姓氏存储在名为 LastName 的字段中,则 WHERE 子句如下所示:
WHERE [LastName]='Bagel'
注释 无须将 WHERE 子句中的条件基于值的等值。可以使用其他比较运算符,如大于 (>) 或小于 (<)。例如,WHERE [Price]>100。
有时您可能希望基于具有匹配数据但数据类型不同的字段来合并数据源。例如,一个表中的某个字段的数据类型可能是“数字”,而您希望将该字段与另一个表中数据类型是“文本”的字段进行比较。
无法在具有不同数据类型的字段之间创建联接。要基于具有不同数据类型的字段中的值合并两个数据源中的数据,可以通过使用 LIKE 关键字创建将一个字段用作另一个字段的条件的 WHERE 子句。
例如,假定您要使用 table1 和 table2 中的数据,但是仅当 field1(table1 中一个文本字段)中的数据与 field2(table2 中的一个数字字段)中的数据匹配时您才会这样做。您的 WHERE 子句会类似于以下内容:
WHERE field1 LIKE field2
有关如何创建要在 WHERE 子句中使用的条件的详细信息,请参阅查询条件示例一文。