分隔标识符(数据库引擎)

符合所有标识符格式规则的标识符可以使用分隔符,也可以不使用分隔符。不符合常规标识符格式规则的标识符必须使用分隔符。

注意注意

MicrosoftSQL Server 无法识别分隔开的变量名和存储过程参数。这些标识符的类型必须符合常规标识符的规则。

带分隔符的标识符用于下列情况:

  • 在对象名称或对象名称的组成部分中使用保留字时。

    保留的关键字不应用作对象名称。从 SQL Server 早期版本升级的数据库可能包含这样的标识符:这些标识符包含在早期版本中不是保留字而在 SQL Server 的当前版本是保留字的字词。在可以改变对象名称之前,可以使用带分隔符的标识符引用对象。

  • 使用未列为限定标识符的字符时。

    SQL Server 允许在带分隔符的标识符中使用当前代码页中的任何字符。但是,不加选择地在对象名称中使用特殊字符会使 SQL 语句和脚本难以阅读和维护。例如,您可以创建名为 Employee] 的表,其中右方括号是名称的一部分。若要执行此操作,必须再使用两个方括号以避免因使用右方括号而出现问题,如下所示:

    CREATE TABLE [Employee]]] 
    (
    EmployeeID int IDENTITY (1,1) NOT NULL,
    FirstName varchar(30),
    LastName varchar(30)
    );
    
注意注意

分隔符仅用于标识符。分隔符不能用于关键字,即使它们在 SQL Server 中标记为保留关键字。

分隔符的类型

以下是在 Transact-SQL 中使用的分隔符类型:

  • 引用的标识符用双引号 (") 分隔开:

    SELECT * FROM "Blanks in Table Name";
    
  • 括在括号中的标识符用方括号 ([ ]) 分隔开:

    SELECT * FROM [Blanks In Table Name];
    

仅当 QUOTED_IDENTIFIER 选项设为 ON 时,引用的标识符才有效。默认情况下,当用于 SQL Server 的 Microsoft OLE DB 访问接口和 SQL Server ODBC 驱动程序连接时,将 QUOTED_IDENTIFIER 设为 ON。

无论使用何种接口,各个应用程序或用户都可以随时更改设置。SQL Server 提供了多种指定该选项的方式。例如,在 SQL Server Management Studio 中,可以在对话框中设置该选项。在 Transact-SQL 中,可以使用 SET QUOTED_IDENTIFIER、ALTER DATABASE 的 QUOTED_IDENTIFIER 选项或 sp_configure 的“用户选项”选项在多个级别设置该选项。

当 QUOTED_IDENTIFIER 设置为 ON 时,SQL Server 按照 ISO 规则在 SQL 语句中使用双引号 (") 和单引号 (')。例如:

  • 双引号只能用于分隔标识符,不能用于分隔字符串。

    为保持与现有应用程序的兼容性,SQL Server 并没有严格遵循该规则。如果字符串未超过标识符的长度,则可以包含在双引号内。我们建议不要这样做。

  • 单引号只用于包含字符串,不能用于分隔标识符。

    如果字符串包含嵌入的单引号,则应在该嵌入的单引号前再添加一个单引号。例如:

    SELECT * FROM "My Table"
    WHERE "Last Name" = 'O''Brien';
    

如果 QUOTED_IDENTIFIER 设为 OFF,对于单引号和双引号的用法,SQL Server 遵循以下规则:

  • 引号不能用于分隔标识符,而必须将括号用作分隔符。

  • 单引号或双引号可用于包含字符串。

    如果使用双引号,嵌入的单引号将不必用两个单引号来表示。例如:

    SELECT * FROM [My Table]
    WHERE [Last Name] = "O'Brien";
    

无论采用哪种 QUOTED_IDENTIFIER 设置,都可以使用括号分隔符。

带分隔符的标识符的规则

带分隔符的标识符的格式规则如下:

  • 带分隔符的标识符可以包含的字符数与常规标识符相同。可以包含 1 到 128 个字符,但不包括分隔符字符。本地临时表标识符最多可以包含 116 个字符。

  • 标识符的主体可以包含当前代码页内字符(分隔符本身除外)的任意组合。例如,带分隔符的标识符可以包含空格、对常规标识符有效的任何字符以及下列任一字符:

    代字号 (~)

    连字符 (-)

    惊叹号 (!)

    左括号 ({)

    百分号 (%)

    右括号 (})

    插入号 (^)

    撇号 (')

    “与”符号 (&)

    句点 (.)

    左圆括号 (()

    反斜杠 (\)

    右圆括号 ())

    重音符号 (`)

  • 如果命名对象时使用了带分隔符的标识符,且对象名称包含尾随空格,则 SQL Server 存储该名称时包含尾随空格。请注意,用于比较标识符名称的语义与用于比较字符串的语义相同。因此,将忽略尾随空格。但是,为了避免将来的兼容性问题,我们建议您认为分隔符内的任何字符都是有意义的,并且建议您用对象的带分隔符的标识符名称来一致地引用该对象。

下面的示例使用带引号的标识符作为表名称和列名称。指定带分隔符的标识符的两种方法如下所示:

SET QUOTED_IDENTIFIER ON;
GO
CREATE TABLE "$Employee Data"
(
 "^First Name"   varchar(25) NOT NULL,
 "^Last Name"   varchar(25) NOT NULL,
 "^Dept ID"   int
);
GO

-- INSERT statements go here.
SET QUOTED_IDENTIFIER OFF;
GO
CREATE TABLE [^$Employee Data]
(
 [^First Name]   varchar(25) NOT NULL,
 [^Last Name]   varchar(25) NOT NULL,
 [^Dept ID]   int
);
GO
-- INSERT statements go here.

创建 $Employee Data 和 ^$Employee Data 表并输入数据后,可以按照以下方式检索行:

SET QUOTED_IDENTIFIER ON;
GO
SELECT * 
FROM "$Employee Data"
SET QUOTED_IDENTIFIER OFF;
GO
-- Or
SELECT *
FROM [^$Employee Data]

在下面的例子中,名为 table 的表包含 tablename、user、select、insert、update 和 delete 各列。由于 TABLE、SELECT、INSERT、UPDATE 和 DELETE 均为保留关键字,因此每次访问对象时都必须分隔标识符。

SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE "table"
(
 tablename char(128) NOT NULL,
 "USER"    char(128) NOT NULL,
 "SELECT"  char(128) NOT NULL,
 "INSERT"  char(128) NOT NULL,
 "UPDATE"  char(128) NOT NULL,
 "DELETE"  char(128) NOT NULL
);
GO

如果 SET QUOTED_IDENTIFIER 选项不为 ON,除非使用括号分隔符,否则不能访问表和列。例如:

SET QUOTED_IDENTIFIER OFF;
GO
SELECT * 
FROM "table";
GO

下面是结果集。:

Msg 170, Level 15, State 1
Line 1: Incorrect syntax near 'table'.

下列语句中使用了括号分隔符,可以访问表和列:

SET QUOTED_IDENTIFIER OFF;
GO
SELECT * 
FROM [table];
GO

将标识符分隔为多个部分

当使用限定对象名称时,可能要分隔组成对象名称的多个标识符。必须分别分隔每个标识符。例如:

/* ISO quoted identifier syntax */
SELECT *
FROM "My DB"."My#UserID"."My.Table";
GO

/* Transact-SQL bracketed identifier syntax */
/* Not available in SQL Server 6.5 or earlier */
SELECT *
FROM [My DB].[My#UserID].[My.Table];
GO

对于如何分隔 ODBC CALL 语句中由多部分组成的存储过程名,有一些特殊规则。有关详细信息,请参阅调用存储过程

在 SQL Server 中将标识符作为参数使用

许多系统存储过程、函数和 DBCC 语句都把对象名称当作参数。其中一些参数接受由多部分组成的对象名称,另一些则只接受由单一部分组成的名称。接受由单一部分组成的名称还是由多部分组成的名称决定了 SQL Server 在内部如何分析和使用参数。

单部分参数名称

如果参数为单部分标识符,则可以按照以下方式指定名称:

  • 无引号或分隔符

  • 包含在单引号内

  • 包含在双引号内

  • 包含在括号内

对于由单一部分组成的名称,单引号内的字符串代表对象名称。如果在单引号内使用分隔符,则分隔符字符将被视为名称的一部分。

如果名称包含句点或常规分隔符所定义的字符集以外的其他字符,必须将对象名称包含在单引号、双引号或括号内。

多部分参数名称

由多部分组成的名称为限定名称,包含数据库或架构名称以及对象名称。将由多部分组成的名称用作参数时,SQL Server 要求将组成该名称的完整字符串包含在一组单引号内。

EXEC MyProcedure @name = 'dbo.Employees';

如果各个名称部分需要使用分隔符,则名称的每一部分都应根据要求单独分隔。例如,如果名称某部分包含句点、双引号、左括号或右括号,则需要使用括号和双引号来分隔该部分。用单引号包含整个名称。

例如,表名 tab.one 包含一个句点。为防止该名称被解释为一个三部分的名称 dbo.tab.one,用分隔符分隔表名部分。

EXEC sp_help 'dbo.[tab.one]';

下面的示例介绍如何用双引号分隔同一表名:

SET QUOTED_IDENTIFIER ON; 
GO 
EXEC sp_help 'dbo."tab.one"';
GO 

更改历史记录

更新的内容

更正了“带分隔符的标识符的规则”下的陈述,指明尾随空格与对象名称一起存储;并且添加了在使用带分隔符的对象名称时的建议的最佳做法。