表提示 (Transact-SQL)

更新日期: 2006 年 12 月 12 日

指定查询优化器使用一个表扫描、一个或多个索引,或为当前表或视图以及当前的 SELECT、INSERT、PDATE 或 DELETE 语句使用锁定方法。虽然这是一个选项,但一般情况下,查询优化器无需指定提示就能选择最佳优化方法。

ms187373.note(zh-cn,SQL.90).gif重要提示:
由于 SQL Server 2005 查询优化器通常为查询选择最优执行计划,因此我们建议,只有在万般无奈的情况下才由经验丰富的开发人员和数据库管理员使用提示(包括 <table_hint>)。

适用范围:

DELETE

INSERT

SELECT

UPDATE

主题链接图标Transact-SQL 语法约定

语法

 <table_hint> ::=  [ NOEXPAND ] {      INDEX ( index_val [ ,...n ] )   | FASTFIRSTROW    | HOLDLOCK    | NOLOCK    | NOWAIT   | PAGLOCK    | READCOMMITTED    | READCOMMITTEDLOCK    | READPAST    | READUNCOMMITTED    | REPEATABLEREAD    | ROWLOCK    | SERIALIZABLE    | TABLOCK    | TABLOCKX    | UPDLOCK    | XLOCK  }   <table_hint_limited> ::= {     KEEPIDENTITY    | KEEPDEFAULTS    | FASTFIRSTROW    | HOLDLOCK    | IGNORE_CONSTRAINTS    | IGNORE_TRIGGERS    | NOWAIT     | PAGLOCK    | READCOMMITTED    | READCOMMITTEDLOCK    | READPAST    | REPEATABLEREAD    | ROWLOCK    | SERIALIZABLE    | TABLOCK    | TABLOCKX    | UPDLOCK    | XLOCK  } 

参数

  • NOEXPAND
    指定查询优化器处理查询时,不扩展任何索引视图来访问基础表。查询优化器将视图当成包含聚集索引的表处理。NOEXPAND 只适用于索引视图。有关详细信息,请参阅“备注”。
  • INDEX ( index_val [ ,... n ] )
    指定查询优化器处理语句时要使用的索引的名称或 ID。只能为每个表指定一个索引提示。

    如果存在聚集索引,则 INDEX(0) 强制执行聚集索引扫描,INDEX(1) 强制执行聚集索引扫描或查找。如果不存在聚集索引,则 INDEX(0) 强制执行表扫描,INDEX(1) 被解释为错误。

    代替的 INDEX = 语法可以指定单个索引提示。支持此语法只是为了向后兼容。

    如果在单个提示列表中使用了多个索引,则将忽略重复项,其余列出的索引将用于检索表中的行。索引提示中的索引顺序很重要。多索引提示还强制执行索引 AND 运算,查询优化器将对每个被访问的索引应用尽可能多的条件。如果带提示的索引集合不是涵盖性的,则在 SQL Server 2005 数据库引擎检索了所有索引列之后,将执行一次提取操作。

    ms187373.note(zh-cn,SQL.90).gif注意:
    如果将引用多个索引的索引提示用于星型联接中的事实数据表,则优化器将忽略索引提示,并返回一个警告消息。另外,不允许对包含指定索引提示的表执行索引 OR 操作。

    表提示中的最大索引数为 250 个非聚集索引。

  • KEEPIDENTITY
    只适用于 INSERT 语句(当 BULK 选项与 OPENROWSET 一起使用时)。

    指定导入数据文件中的标识值用于标识列。如果不指定 KEEPIDENTITY,则将验证但不导入此列的标识值。查询优化器将根据创建表时指定的种子值和增量值自动分配唯一值。

    ms187373.note(zh-cn,SQL.90).gif重要提示:
    如果数据文件不包含表或视图中的标识列的值,那么,除非标识列是表中的最后一列,否则必须跳过标识列。有关详细信息,请参阅使用格式化文件跳过数据字段。如果成功跳过了一个标识列,则查询优化器会自动将标识列的唯一值分配到导入表行中。

    有关在 INSERT ...SELECT * FROM OPENROWSET(BULK...) 语句中使用此提示的示例,请参阅大容量导入数据时保留标识值

    有关检查表的标识值的信息,请参阅 DBCC CHECKIDENT (Transact-SQL)

  • KEEPDEFAULTS
    只适用于 INSERT 语句(当 BULK 选项与 OPENROWSET 一起使用时)。

    如果列的数据记录缺少值,则指定插入用于代替 NULL 的表列的默认值(如果有)。

    有关在 INSERT ...SELECT * FROM OPENROWSET(BULK...) 语句中使用此提示的示例,请参阅在大容量导入期间保留空值或使用默认值

  • FASTFIRSTROW
    等同于 OPTION (FAST 1)。有关详细信息,请参阅 SELECT 的 OPTION 字句中的 FAST。
  • HOLDLOCK
    等同于 SERIALIZABLE。有关详细信息,请参阅本主题后面的 SERIALIZABLE。HOLDLOCK 仅应用于那些为其指定了 HOLDLOCK 的表或视图,并且仅在使用了 HOLDLOCK 的语句定义的事务的持续时间内应用。HOLDLOCK 不能被用于包含 FOR BROWSE 选项的 SELECT 语句。
  • IGNORE_CONSTRAINTS
    只适用于 INSERT 语句(当 BULK 选项与 OPENROWSET 一起使用时)。

    指定大容量导入操作将忽略对表的任何约束。默认情况下,INSERT 检查 CHECKFOREIGN KEY 约束。当为大容量导入操作指定 IGNORE_CONSTRAINTS 时,INSERT 必须忽略对目标表的这些约束。注意,您无法禁用 UNIQUE、PRIMARY KEY 或 NOT NULL 约束。

    如果输入数据包含违反约束的行,则可能会出现希望禁用 CHECK 和 FOREIGN KEY 约束的情况。通过禁用 CHECK 和 FOREIGN KEY 约束,可以导入数据,然后使用 Transact-SQL 语句清除该数据。

    不过请注意,当忽略 CHECK 和 FOREIGN KEY 约束时,操作之后表的每个被忽略的约束都将在 sys.check_constraintssys.foreign_keys 目录视图中标记为 is_not_trusted。在某些点,需要检查整个表的约束。如果在大容量导入操作之前表不为空,则重新验证约束的开销可能超过对增量数据应用 CHECK 和 FOREIGN KEY 约束的开销。

  • IGNORE_TRIGGERS
    只适用于 INSERT 语句(当 BULK 选项与 OPENROWSET 一起使用时)。

    指定大容量导入操作将忽略为表定义的所有触发器。默认情况下,INSERT 将应用触发器。

    仅当应用程序不依赖任何触发器,并且必须最大程度地提高性能时,才使用 IGNORE_TRIGGERS。

  • NOLOCK
    等同于 READUNCOMMITTED。有关详细信息,请参阅本主题后面的 READUNCOMMITTED。
  • NOWAIT
    指示 SQL Server 2005 数据库引擎在遇到表的锁时,立即返回一个消息。NOWAIT 等同于将特定表的 SET LOCK_TIMEOUT 值指定为 0。
  • PAGLOCK
    在通常行或键采用单个锁的地方,或者通常采用单个表锁的地方,请采用页锁。默认情况下,请使用与操作相对应的锁模式。在从 SNAPSHOT 隔离级别操作的事务中指定时,除非将 PAGLOCK 与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合,否则不会取得页锁。
  • READCOMMITTED
    指定读操作使用锁定或行版本控制来遵循有关 READ COMMITTED 隔离级别的规则。如果数据库选项 READ_COMITTED_SNAPSHOT 为 OFF,则数据库引擎将在读取数据时获取共享锁,在读操作完成时释放这些锁。如果数据库选项 READ_COMMITTED_SNAPSHOT 为 ON,则数据库引擎不获取锁,并使用行版本控制。有关隔离级别的详细信息,请参阅 SET TRANSACTION ISOLATION LEVEL (Transact-SQL)
  • READCOMMITTEDLOCK
    指定读操作使用锁定来遵循有关 READ COMMITTED 隔离级别的规则。无论 READ_COMMITTED_SNAPSHOT 数据库选项的设置如何,数据库引擎都将在读取数据时获取共享锁,在读操作完成后释放这些锁。有关隔离级别的详细信息,请参阅 SET TRANSACTION ISOLATION LEVEL (Transact-SQL)
  • READPAST
    指定数据库引擎不读取由其他事务锁定的行。在大多数情况下,这同样适用于页。数据库引擎跳过这些行或页,而不是在释放锁之前阻塞当前事务。仅可在运行于 READ COMMITTED 或 REPEATABLE READ 隔离级别的事务中指定 READPAST。在从 SNAPSHOT 隔离级别操作的事务中指定时,READPAST 必须与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合。如果指定了 READPAST,则将跳过行级别锁和页级别锁。可为 UPDATE 或 DELETE 语句中以及 FROM 子句中引用的任何表指定 READPAST。如果 READPAST 是在 UPDATE 语句中指定的,则仅当读取数据以标识要更新的记录时才应用 READPAST,而不考虑语句中指定 READPAST 的位置。不能为 INSERT 语句的 INTO 子句中的表指定 READPAST。

    使用 READPAST 的读操作不会发生阻塞。读取外键或索引视图或者修改辅助索引时,使用 READPAST 的更新或删除操作可能发生阻塞。

    例如,假定表 T1 包含一个单精度整数列,其值为 1、2、3、4 和 5。如果事务 A 将值 3 值改为 8,但尚未提交,则 SELECT * FROM T1 (READPAST) 将生成值 1、2、4 和 5。使用 SQL Server 表实现工作队列时,READPAST 主要用于减少锁定争用。使用 READPAST 的队列读取器会跳过被其他事务锁定的队列项,跳至下一个可用的队列项,而不是等待其他事务释放锁。

  • READUNCOMMITTED
    指定允许脏读。不发布共享锁来阻止其他事务修改当前事务在读的数据,其他事务设置的排他锁不会阻碍当前事务读取锁定数据。允许脏读可能产生较多的并发操作,但其代价是读取以后会被其他事务回滚的数据修改。这可能会生成事务的错误,或向用户显示从未提交过的数据。

    READUNCOMMITTED 和 NOLOCK 提示仅适用于数据锁。所有查询(包括那些带有 READUNCOMMITTED 和 NOLOCK 提示的查询)都会在编译和执行过程中获取 Sch-S(架构稳定性)锁。因此,当并发事务持有表的 Sch-M(架构修改)锁时,将阻塞查询。例如,数据定义语言 (DDL) 操作在修改表的架构信息之前获取 Sch-M 锁。所有并发查询(包括那些使用 READUNCOMMITTED 或 NOLOCK 提示运行的查询)都会在尝试获取 Sch-S 琐时被阻塞。相反,持有 Sch-S 锁的查询将阻塞尝试获取 Sch-M 锁的并发事务。有关锁行为的详细信息,请参阅锁兼容性(数据库引擎)

    不能为通过插入、更新或删除操作修改过的表指定 READUNCOMMITTED 和 NOLOCK。SQL Server 查询优化器忽略 FROM 子句中应用于 UPDATE 或 DELETE 语句的目标表的 READUNCOMMITTED 和 NOLOCK 提示。

    ms187373.note(zh-cn,SQL.90).gif注意:
    在 Microsoft SQL Server 的未来版本中,将不再支持在 FROM 子句中使用应用于 UPDATE 或 DELETE 语句目标表的 READUNCOMMITTED 和 NOLOCK 提示。请避免在新的开发工作上下文中使用这些提示,并计划修改当前使用它们的应用程序。

    在 SQL Server 2005 中,可以使用以下任意一种方法,最大程度地减少保护事务处理避免对未提交的数据修改进行脏读时的锁定争用:

    • READ COMMITTED 隔离级别,其中 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON。
    • SNAPSHOT 隔离级别。

    有关隔离级别的详细信息,请参阅 SET TRANSACTION ISOLATION LEVEL (Transact-SQL)

    ms187373.note(zh-cn,SQL.90).gif注意:
    如果在指定了 READUNCOMMITTED 的情况下收到 601 号错误消息,则按解决死锁错误 (1205) 的方法解决该错误,然后重试语句。
  • ROWLOCK
    指定通常采用页锁或表锁时,采用行锁。在从 SNAPSHOT 隔离级别操作的事务中指定时,除非将 ROWLOCK 与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合,否则不会取得行锁。
  • SERIALIZABLE
    等同于 HOLDLOCK。保持共享锁直到事务完成,使共享锁更具有限制性;而不是无论事务是否完成,都在不再需要所需表或数据页时立即释放共享锁。执行扫描时所用的语义与在 SERIALIZABLE 隔离级别运行的事务的语义相同。有关隔离级别的详细信息,请参阅 SET TRANSACTION ISOLATION LEVEL (Transact-SQL)
  • TABLOCK
    指定对表采用锁并一直保持到语句结束。如果正在读取数据,则采用共享锁。如果正在修改数据,则采用排他锁。如果同时指定了 HOLDLOCK,那么,在事务结束之前将一直保持共享表锁。

    如果与 OPENROWSET 大容量行集提供程序一起用于将数据导入无索引的表,则 TABLOCK 将启用多个客户端,同时将数据加载到包含优化日志记录和锁定的目标表中。

  • TABLOCKX
    指定对表采用排他锁直至事务完成。
  • UPDLOCK
    指定采用更新锁并保持到事务完成。
  • XLOCK
    指定采用排他锁并保持到事务完成。如果同时指定了 ROWLOCK, PAGLOCK 或 TABLOCK,则排他锁将应用于相应的粒度级别。

备注

如果查询计划不访问表,则将忽略表提示。这可能是由于优化器选择了完全不访问该表,也可能是因为改成了访问索引视图。在后一种情况中,使用 OPTION (EXPAND VIEWS) 查询提示可阻止访问索引视图。

鼓励在表提示之间使用逗号,尽管这是可选的。为保持向后兼容,支持使用空格而不是逗号来分隔提示。

在 SQL Server 2005 中,除一些例外情况之外,仅当使用了 WITH 关键字指定表提示时,FROM 子句中才支持这些提示。指定表提示时必须使用括号。

使用或不使用 WITH 关键字均可使用的表提示如下:NOLOCK、READUNCOMMITTED、UPDLOCK、REPEATABLEREAD、SERIALIZABLE、READCOMMITTED、FASTFIRSTROW、TABLOCK、TABLOCKX、PAGLOCK、ROWLOCK、NOWAIT、READPAST、XLOCK 和 NOEXPAND。如果指定的表提示不含 WITH 关键字,则必须单独指定该提示。例如:

FROM t (FASTFIRSTROW)

如果指定的提示含其他选项,则指定的提示必须含 WITH 关键字:

FROM t WITH (FASTFIRSTROW, INDEX(myindex))

如果在对兼容级别为 90 的数据库的查询中使用提示,则将应用限制。

在 SQL Server 2005 中,所有锁提示都被传播给视图中引用的所有表和视图。另外,SQL Server 还将执行对应的锁一致性检查。

获取行级别锁的锁提示 ROWLOCK、UPDLOCK 和 XLOCK,则可能对索引键而不是实际的数据行采用锁。例如,如果表具有非聚集索引,而且由涵盖索引处理使用锁提示的 SELECT 语句,则将对涵盖索引中的索引键而不是对基表中的数据行采用锁。

如果某个表包含计算列,而该计算列是由访问其他某些表中的列的表达式或函数计算的,则不对这些表使用表提示,即不传播表提示。例如,对查询中的表指定 NOLOCK 表提示。此表包含的计算列是由访问另一表中的列的表达式和函数组合计算的。表达式和函数引用的表在被访问时将不使用 NOLOCK 表提示。

对于 FROM 子句中的每个表,SQL Server 不允许存在多个来自以下各个组的表提示:

  • 粒度提示:PAGLOCK、NOLOCK、ROWLOCK、TABLOCK 或 TABLOCKX。
  • 隔离级别提示:HOLDLOCK、NOLOCK、READCOMMITTED、REPEATABLEREAD 和 SERIALIZABLE。

使用 NOEXPAND

NOEXPAND 只适用于索引视图。索引视图是包含为其创建的唯一聚集索引的视图。如果查询包含对同时存在于索引视图和基表中的列的引用,而且查询优化器确定执行查询的最佳方法是使用索引视图,则查询优化器将对视图使用索引。此函数称为“索引视图匹配**”,只有 SQL Server 2005 Enterprise 版本和 Developer 版本支持此函数。

但是,为了使优化器考虑使用索引视图进行匹配或在引用索引视图时使用 NOEXPAND 提示,必须将以下 SET 选项设置为 ON:

ANSI_NULLS

ANSI_WARNINGS

CONCAT_NULL_YIELDS_NULL

ANSI_PADDING

ARITHABORT1

QUOTED_IDENTIFIERS

1 如果 ANSI_WARNINGS 设置为 ON,则 ARITHABORT 将隐式设置为 ON。因此,不必手动调整此设置。

另外,必须将 NUMERIC_ROUNDABORT 选项设置为 OFF。

若要强制优化器对索引视图使用索引,请指定 NOEXPAND 选项。仅当查询中也命名了该视图时才能使用此提示。如果某个查询没有在 FROM 子句直接命名视图,则 SQL Server 2005 不提供在该查询中强制采用特定索引视图的提示;但是,即使查询中未直接引用索引视图,查询优化器仍会考虑使用索引视图。

有关详细信息,请参阅解析视图的索引

权限

KEEPIDENTITY、IGNORE_CONSTRAINTS 和 IGNORE_TRIGGERS 提示需要有对表的 ALTER 权限。

示例

以下示例指定对 Production.Product 表采用共享锁,并保持到 UPDATE 语句结束。

UPDATE Production.Product
WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%'

请参阅

参考

OPENROWSET (Transact-SQL)
提示 (Transact-SQL)

其他资源

锁定提示
视图解析

帮助和信息

获取 SQL Server 2005 帮助

更改历史记录

发布日期 历史记录

2006 年 12 月 12 日

更改的内容:
  • 明确了由 TABLOCK 提示采用的锁的类型。
  • 修改了 IGNORE_CONSTRAINTS 提示的说明,指出该提示可导致同时忽略 CHECK 和 FOREIGN KEY 约束。

2006 年 4 月 14 日

新增内容:
  • 添加了在从 SNAPSHOT 隔离级别操作的事务中使用 PAGLOCK、READPAST 和 ROWLOCK 的相关信息。

2005 年 12 月 5 日

更改的内容:
  • 更新了有关 READUNCOMMITTED 锁提示的信息。