ALTER TABLE (Transact-SQL)

通过更改、添加或删除列和约束,重新分配分区,或者启用或禁用约束和触发器,从而修改表的定义。

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

语法

ALTER TABLE [ database_name . [ schema_name ] . | schema_name . ] table_name 
{ 
    ALTER COLUMN column_name 
    { 
        [ type_schema_name. ] type_name [ ( { precision [ ,scale ] 
            | max | xml_schema_collection } ) ] 
        [ COLLATE collation_name ] 
        [ SPARSE | NULL | NOT NULL ] 
    | {ADD | DROP } 
        { ROWGUIDCOL | PERSISTED | NOT FOR REPLICATION | SPARSE }
    } 
        | [ WITH { CHECK | NOCHECK } ]

    | ADD 
    { 
        <column_definition>
      | <computed_column_definition>
      | <table_constraint> 
      | <column_set_definition> 
    } [ ,...n ]

    | DROP 
    { 
        [ CONSTRAINT ] constraint_name 
        [ WITH ( <drop_clustered_constraint_option> [ ,...n ] ) ]
        | COLUMN column_name 
    } [ ,...n ] 

    | [ WITH { CHECK | NOCHECK } ] { CHECK | NOCHECK } CONSTRAINT 
        { ALL | constraint_name [ ,...n ] } 

    | { ENABLE | DISABLE } TRIGGER 
        { ALL | trigger_name [ ,...n ] }

    | { ENABLE | DISABLE } CHANGE_TRACKING 
        [ WITH ( TRACK_COLUMNS_UPDATED = { ON | OFF } ) ]

    | SWITCH [ PARTITION source_partition_number_expression ]
        TO target_table 
        [ PARTITION target_partition_number_expression ]

    | SET ( FILESTREAM_ON = { partition_scheme_name | filegroup | 
                "default" | "NULL" } )

    | REBUILD 
      [ [PARTITION = ALL]
        [ WITH ( <rebuild_option> [ ,...n ] ) ] 
      | [ PARTITION = partition_number 
           [ WITH ( <single_partition_rebuild_option> [ ,...n ] ) ]
        ]
      ]

    | (<table_option>)
}
[ ; ]

<column_set_definition> ::= 
    column_set_name XML COLUMN_SET FOR ALL_SPARSE_COLUMNS

<drop_clustered_constraint_option> ::=  
    { 
        MAXDOP = max_degree_of_parallelism      | ONLINE = {ON | OFF }
      | MOVE TO { partition_scheme_name (column_name) | filegroup
          | "default" }
    }
<table_option> ::=
    {
        SET ( LOCK_ESCALATION = { AUTO | TABLE | DISABLE } )
    }

<single_partition_rebuild__option> ::=
{
      SORT_IN_TEMPDB = { ON | OFF }
    | MAXDOP =max_degree_of_parallelism
    | DATA_COMPRESSION = { NONE | ROW | PAGE} }
}

参数

  • database_name
    要在其中创建表的数据库的名称。

  • schema_name
    表所属架构的名称。

  • table_name
    要更改的表的名称。如果表不在当前数据库中,或者不包含在当前用户所拥有的架构中,则必须显式指定数据库和架构。

  • ALTER COLUMN
    指定要更改命名列。有关详细信息,请参阅sp_dbcmptlevel (Transact-SQL)

    修改后的列不能为下列任何一种列:

    • 数据类型为 timestamp 的列。

    • 表的 ROWGUIDCOL 列。

    • 计算列或用于计算列的列。

    • 用在索引中的列,除非该列数据类型为 varchar、nvarchar 或 varbinary,数据类型没有更改,新的大小等于或者大于旧的大小并且索引不是 PRIMARY KEY 约束的结果。

    • 用在 CREATE STATISTICS 语句生成的统计信息中的列,除非该列的数据类型为 varchar、nvarchar 或 varbinary,数据类型没有更改,新的大小等于或大于旧的大小,或者该列从非 NULL 更改为 NULL。首先,用 DROP STATISTICS 语句删除统计信息。由查询优化器自动生成的统计信息将被 ALTER COLUMN 自动删除。

    • 用于 PRIMARY KEY 或 [FOREIGN KEY] REFERENCES 约束中的列。

    • 用于 CHECK 或 UNIQUE 约束中的列。但是,允许更改用于 CHECK 或 UNIQUE 约束中的长度可变的列的长度。

    • 与默认定义关联的列。但是,如果不更改数据类型,则可以更改列的长度、精度或小数位数。

      仅能通过下列方式更改 text、ntext 和 image 列的数据类型:

      • text 改为 varchar(max)、nvarchar(max) 或 xml

      • ntext 改为 varchar(max)、nvarchar(max) 或 xml

      • image 改为varbinary(max)

      某些数据类型的更改可能导致数据的更改。例如,如果将 nchar 或 nvarchar 列改为 char 或 varchar,则可能导致转换扩展字符。有关详细信息,请参阅 CAST 和 CONVERT (Transact-SQL)。降低列的精度或减少小数位数可能导致数据截断。

      无法更改已分区表的列的数据类型。

  • column_name
    要更改、添加或删除的列的名称。column_name 最多可以包含 128 个字符。对于新列,如果创建列时使用的数据类型为 timestamp,则可以省略 column_name。如果没有为 timestamp 数据类型列指定 column_name,则使用名称 timestamp。

  • [ type_schema_name**.**] type_name
    更改后的列的新数据类型或添加的列的数据类型。不能为已分区表的现有列指定 type_name。type_name 可以为下列任意一种类型:

    • SQL Server 系统数据类型。

    • 基于 SQL Server 系统数据类型的别名数据类型。必须先用 CREATE TYPE 语句创建别名数据类型,然后才能将其用于表定义中。

    • .NET Framework 用户定义类型及其所属的架构。只有在使用 CREATE TYPE 语句创建了 .NET Framework 用户定义类型后,才能将其用于表定义。

    更改后的列的 type_name 应符合下列条件:

    • 以前的数据类型必须可以隐式转换为新数据类型。

    • type_name 不能为 timestamp。

    • 对于 ALTER COLUMN,ANSI_NULL 默认值始终为 ON;如果没有指定,列可为空。

    • 对于 ALTER COLUMN,ANSI_PADDING 填充始终为 ON。

    • 如果修改后的列是标识列,则 new_data_type 必须是支持标识属性的数据类型。

    • 当前的 SET ARITHABORT 设置将被忽略。ALTER TABLE 的操作方式与 ARITHABORT 设置为 ON 时相同。

    注意注意

    如果未指定 COLLATE 子句,则更改列的数据类型将导致更改数据库的默认排序规则。

  • precision
    指定的数据类型的精度。有关有效精度值的详细信息,请参阅精度、小数位数和长度 (Transact-SQL)

  • scale
    是指定数据类型的小数位数。有关有效小数位数值的详细信息,请参阅精度、小数位数和长度 (Transact-SQL)

  • max
    仅应用于 varchar、nvarchar 和 varbinary 数据类型,以便存储 2^31-1 个字节的字符、二进制数据以及 Unicode 数据。

  • xml_schema_collection
    仅应用于 xml 数据类型,以便将 XML 架构与类型相关联。在架构集合中键入 xml 列之前,必须首先使用 CREATE XML SCHEMA COLLECTION 在数据库中创建架构集合。

  • COLLATE < collation_name >
    指定更改后的列的新排序规则。如果未指定,则为该列分配数据库的默认排序规则。排序规则名称既可以是 Windows 排序规则名称,也可以是 SQL 排序规则名称。有关列表及详细信息,请参阅 Windows 排序规则名称 (Transact-SQL)SQL Server 排序规则名称 (Transact-SQL)

    COLLATE 子句只能用来更改数据类型为 char、varchar、nchar 和 nvarchar 的列的排序规则。若要更改用户定义别名数据类型列的排序规则,必须执行单独的 ALTER TABLE 语句,将列改为 SQL Server 系统数据类型,并更改其排序规则,然后重新将列改为别名数据类型。

    如果出现以下一种或多种情况,则 ALTER COLUMN 不能更改排序规则:

    • CHECK 约束、FOREIGN KEY 约束或计算列引用了更改后的列。

    • 已为列创建了索引、统计信息或全文索引。如果更改了列的排序规则,则将删除为更改后的列自动创建的统计信息。

    • 绑定到架构的视图或函数引用了列。

    有关详细信息,请参阅 COLLATE (Transact-SQL)

  • SPARSE | NULL | NOT NULL
    指定列是否是稀疏列或是否可接受 null 值。如果要更改的列是稀疏列,则您必须显式指定该属性,否则该列将恢复为非稀疏列。不能将稀疏列指定为 NOT NULL。将列从稀疏列转换为非稀疏列或者从非稀疏列转换为稀疏列会导致表在命令执行期间被锁定。

    有关稀疏列以及为 Null 性的其他限制和详细信息,请参阅使用稀疏列

    如果列不允许 Null 值,则只有在为列指定了默认值或整个表为空的情况下,才能用 ALTER TABLE 语句添加该列。只有同时指定了 PERSISTED 时,才能为计算列指定 NOT NULL。如果新列允许空值,但没有指定默认值,则新列在表中的每一行都包含一个空值。如果新列允许空值,并且指定了新列的默认值,则可以使用 WITH VALUES 将默认值存储到表中每个现有行的新列中。

    如果新列不允许空值,并且表不为空,那么 DEFAULT 定义必须与新列一起添加;并且,加载新列时,每个现有行的新列中将自动包含默认值。

    在 ALTER COLUMN 语句中指定 NULL,可以强制 NOT NULL 列允许空值,但 PRIMARY KEY 约束中的列除外。只有列中不包含空值时,才可以在 ALTER COLUMN 中指定 NOT NULL。必须将空值更新为某个值后,才允许执行 ALTER COLUMN NOT NULL 语句,例如:

    UPDATE MyTable SET NullCol = N'some_value' WHERE NullCol IS NULL
    ALTER TABLE MyTable ALTER COLUMN NullCOl NVARCHAR(20) NOT NULL
    

    如果用 CREATE TABLE 或 ALTER TABLE 语句创建或更改表,则数据库或会话设置将影响并且可能覆盖用于列定义的数据类型的为空性。建议您始终针对非计算列将某一列显式定义为 NULL 或 NOT NULL。

    如果添加具有用户定义的数据类型的列,则建议您将该列的为 Null 性定义为与用户定义的数据类型的 null 属性相同,并为该列指定一个默认值。有关详细信息,请参阅 CREATE TABLE (Transact-SQL)

    注意注意

    如果 ALTER COLUMN 与 NULL 或 NOT NULL 一起指定,则必须同时指定 new_data_type [(precision [, scale ])]。如果未更改数据类型、精度和小数位数,则指定当前的列值。

  • [ {ADD | DROP} ROWGUIDCOL ]
    指定在指定列中添加或删除 ROWGUIDCOL 属性。ROWGUIDCOL 指示列为行 GUID 列。每个表中只有一个 uniqueidentifier 列能指定为 ROWGUIDCOL 列,并且只能为 uniqueidentifier 列分配 ROWGUIDCOL 属性。不能将 ROWGUIDCOL 分配给用户定义数据类型的列。

    ROWGUIDCOL 不强制要求列中存储的值的唯一性,也不为插入到表中的新行自动生成值。若要为每列生成唯一值,则可以在 INSERT 语句中使用 NEWID 函数,也可以将 NEWID 函数指定为列的默认值。

  • [ {ADD | DROP} PERSISTED ]
    指定在指定列中添加或删除 PERSISTED 属性。该列必须是由确定性表达式定义的计算列。对于指定为 PERSISTED 的列,数据库引擎将以物理方式在表中存储计算值;并且,当更新了计算列依赖的任何其他列时,这些值也将被更新。通过将计算列标记为 PERSISTED,可以对确定(但不精确)的表达式中定义的计算列创建索引。有关详细信息,请参阅为计算列创建索引

    用作已分区表的分区依据列的任何计算列必须显式标记为 PERSISTED。

  • DROP NOT FOR REPLICATION
    指定当复制代理执行插入操作时,标识列中的值将增加。只有当 column_name 是标识列时,才可以指定此子句。有关详细信息,请参阅使用 NOT FOR REPLICATION 来控制约束、标识和触发器

  • SPARSE
    指定要添加或删除的列是稀疏列。稀疏列已针对 NULL 值进行了存储优化。不能将稀疏列指定为 NOT NULL。将列从稀疏列转换为非稀疏列或者从非稀疏列转换为稀疏列会导致表在命令执行期间被锁定。

    注意注意

    必须在每次更改该列时都指定 SPARSE 属性,否则该列将恢复为非稀疏列。

    有关稀疏列的其他限制和详细信息,请参阅使用稀疏列

  • WITH CHECK | WITH NOCHECK
    指定表中的数据是否用新添加的或重新启用的 FOREIGN KEY 或 CHECK 约束进行验证。如果未指定,对于新约束,假定为 WITH CHECK,对于重新启用的约束,假定为 WITH NOCHECK。

    如果不想根据现有数据验证新的 CHECK 或 FOREIGN KEY 约束,请使用 WITH NOCHECK。除极个别的情况外,建议不要进行这样的操作。在以后所有数据更新中,都将计算该新约束。如果添加约束时用 WITH NOCHECK 禁止了约束冲突,则将来使用不符合该约束的数据来更新行时,可能导致更新失败。

    查询优化器不考虑使用 WITH NOCHECK 定义的约束。在使用 ALTER TABLE table CHECK CONSTRAINT ALL 语句重新启用这些约束之前,将忽略这些约束。

  • ADD
    指定添加一个或多个列定义、计算列定义或者表约束。

  • DROP { [ CONSTRAINT ] constraint_name | COLUMN column_name }
    指定从表中删除 constraint_name 或 column_name。可以列出多个列或约束。

    可通过查询 sys.check_constraintsys.default_constraintssys.key_constraintssys.foreign_keys 目录视图来确定约束的用户定义名称或系统提供的名称。

    如果表中存在 XML 索引,则不能删除 PRIMARY KEY 约束。

    无法删除以下列:

    • 用于索引的列。

    • 用于 CHECK、FOREIGN KEY、UNIQUE 或 PRIMARY KEY 约束的列。

    • 与默认值(由 DEFAULT 关键字定义)相关联的列,或绑定到默认对象的列。

    • 绑定到规则的列。

    注意注意

    删除列并不回收列所占的磁盘空间。当表的行大小接近或超过其限额时,必须回收已删除的列占用的磁盘空间。通过创建表的聚集索引或使用 ALTER INDEX 重新生成现有的聚集索引,可以回收空间。

  • WITH <drop_clustered_constraint_option>
    指定设置一个或多个删除聚集约束选项。

  • MAXDOP = max_degree_of_parallelism
    只在操作期间覆盖 max degree of parallelism 配置选项。有关详细信息,请参阅max degree of parallelism 选项

    使用 MAXDOP 选项来限制执行并行计划时所用的处理器数量。最大数量为 64 个处理器。

    max_degree_of_parallelism 可以是下列值之一:

    • 1
      取消生成并行计划。

    • >1
      将并行索引操作中使用的最大处理器数量限制为指定数量。

    • 0(默认值)
      根据当前系统工作负荷使用实际的处理器数量或更少数量的处理器。

    有关详细信息,请参阅配置并行索引操作

    注意注意

    并行索引操作仅在 SQL Server Enterprise Edition、Developer Edition 和 Evaluation Edition 中可用。

  • ONLINE = { ON | OFF }
    指定在索引操作期间基础表和关联的索引是否可用于查询和数据修改操作。默认为 OFF。REBUILD 可作为 ONLINE 操作执行。

    • ON
      在索引操作期间不持有长期表锁。在索引操作的主要阶段,源表上只使用意向共享 (IS) 锁。这使得能够继续对基础表和索引进行查询或更新。操作开始时,将对源对象保持极短时间的共享 (S) 锁。操作结束时,如果创建非聚集索引,将在短期内对源获取 S(共享)锁;当联机创建或删除聚集索引时,以及重新生成聚集或非聚集索引时,将在短期内获取 SCH-M(架构修改)锁。对本地临时表创建索引时,ONLINE 不能设置为 ON。仅允许单线程 HEAP 重新生成操作。

    • OFF
      在索引操作期间应用表锁。创建、重新生成或删除聚集索引或者重新生成或删除非聚集索引的脱机索引操作将对表获取架构修改 (Sch-M) 锁。这样可以防止所有用户在操作期间访问基础表。创建非聚集索引的脱机索引操作将对表获取共享 (S) 锁。这样可以防止更新基础表,但允许读操作(如 SELECT 语句)。允许多线程 HEAP 重新生成操作。

    有关详细信息,请参阅联机索引操作的工作方式。有关锁的详细信息,请参阅锁模式

    注意注意

    联机索引操作仅在 SQL Server Enterprise Edition、Developer Edition 和 Evaluation Edition 中可用。

  • MOVE TO { partition_scheme_name**(** column_name [ 1**,** ... n]) | filegroup | "default" }
    指定一个位置以移动聚集索引的叶级别中的当前数据行。表被移至新位置。

    注意注意

    在此上下文中,default 不是关键字。它是默认文件组的标识符,必须对其进行分隔,就像在 MOVE TO "default" 或 MOVE TO [default] 中一样。如果指定了 "default",则当前会话的 QUOTED_IDENTIFIER 选项必须为 ON。这是默认设置。有关详细信息,请参阅 SET QUOTED_IDENTIFIER (Transact-SQL)

  • { CHECK | NOCHECK} CONSTRAINT
    指定启用或禁用 constraint_name。此选项只能与 FOREIGN KEY 和 CHECK 约束一起使用。如果指定了 NOCHECK,则将禁用约束,从而在将来插入或更新列时,不根据约束条件进行验证。无法禁用 DEFAULT、PRIMARY KEY 和 UNIQUE 约束。

  • ALL
    指定使用 NOCHECK 选项禁用所有约束,或者使用 CHECK 选项启用所有约束。

  • {ENABLE | DISABLE} TRIGGER
    指定启用或禁用 trigger_name。禁用触发器时,仍会为表定义该触发器;但是,当对表执行 INSERT、UPDATE 或 DELETE 语句时,除非重新启用触发器,否则不会执行触发器中的操作。

  • ALL
    指定启用或禁用表中的所有触发器。

  • trigger_name
    指定要启用或禁用的触发器的名称。

  • { ENABLE | DISABLE } CHANGE_TRACKING
    指定是启用还是禁用表的更改跟踪。默认情况下会禁用更改跟踪。

    只有对数据库启用了更改跟踪,此选项才可用。有关详细信息,请参阅 ALTER DATABASE SET 选项 (Transact-SQL)

    若要启用更改跟踪,表必须具有一个主键。

  • WITH ( TRACK_COLUMNS_UPDATED = { ON | OFF } )
    指定数据库引擎是否跟踪哪些更改跟踪列已更新。默认值为 OFF。

  • SWITCH [ PARTITION source_partition_number_expression ] TO [ schema_name**.**] target_table [ PARTITION target_ partition_number_expression ]
    用下列方式之一切换数据块:

    • 将表的所有数据作为分区重新分配给现有的已分区表。

    • 将分区从一个已分区表切换到另一个已分区表。

    • 将已分区表的一个分区中的所有数据重新分配给现有的未分区的表。

    如果 table 为已分区表,则必须指定 source_partition_number_expression。如果 target_table 已进行分区,则必须指定 target_partition_number_expression。如果要将表的数据作为分区重新分配给现有的已分区表,或者将分区由一个已分区表切换到另一个已分区表,则目标分区必须存在,并且必须为空。

    如果重新分配一个分区的数据以组成单个表,则必须已经创建了目标表,并且该表必须为空。源表或分区以及目标表或分区必须在同一个文件组中。对应的索引或索引分区也必须在同一个文件组中。切换分区还有许多其他限制。有关详细信息,请参阅使用分区切换高效传输数据。table 和 target_table 不能相同。target_table 可以是由多个部分构成的标识符。

    source_partition_number_expression 和 target_partition_number_expression 为常量表达式,可以引用变量和函数,其中包括用户定义类型变量和用户定义函数。它们不能引用 Transact-SQL 表达式。 

    注意注意

    不能对复制表使用 SWITCH 语句。

  • SET ( FILESTREAM_ON = { partition_scheme_name | filestream_filegroup_name | "default" | "NULL" })
    指定 FILESTREAM 数据的存储位置。

    带有 SET FILESTREAM_ON 子句的 ALTER TABLE 只有在表不包含任何 FILESTREAM 列时才会成功。可以通过使用第二个 ALTER TABLE 语句添加 FILESTREAM 列。

    如果指定 partition_scheme_name,则会应用 CREATE TABLE 的规则。表应该已经对行数据进行了分区,并且其分区方案必须使用与 FILESTREAM 分区方案相同的分区函数和分区列。

    filestream_filegroup_name 指定 FILESTREAM 文件组的名称。该文件组必须包含一个使用 CREATE DATABASEALTER DATABASE 语句为该文件组定义的文件;否则,将引发错误。

    "default" 指定 FILESTREAM 文件组具有 DEFAULT 属性集。如果没有 FILESTREAM 文件组,将引发错误。

    "NULL" 指定对表的 FILESTREAM 文件组的所有引用都将被删除。首先必须删除所有 FILESTREAM 列。必须使用 SET FILESTREAM_ON**="NULL"** 删除与表关联的所有 FILESTREAM 数据。

  • SET ( LOCK_ESCALATION = { AUTO | TABLE | DISABLE } )
    指定允许的对表的锁进行升级的方法。

    • AUTO
      此选项允许 SQL Server 数据库引擎 选择适合于表架构的锁升级粒度。

      • 如果该表已分区,则允许将锁升级到分区。锁升级到分区级别之后,该锁以后将不会升级到 TABLE 粒度。

      • 如果该表未分区,则会将锁升级到 TABLE 粒度。

    • TABLE
      无论表是否已分区,都会在表级粒度完成锁升级。此行为与 SQL Server 2005 中相同。默认值为 TABLE。

    • DISABLE
      在大多数情况下禁止锁升级。表级别的锁未完全禁止。例如,当扫描在可序列化隔离级别下没有聚集索引的表时,数据库引擎必须使用表锁来保证数据的完整性。

  • REBUILD
    使用 REBUILD WITH 语法可重新生成包含分区表中的所有分区的整个表。如果表具有聚集索引,则 REBUILD 选项将重新生成该聚集索引。REBUILD 可作为 ONLINE 操作执行。

    使用 REBUILD PARTITION 语法可重新生成分区表中的单个分区。

  • PARTITION = ALL
    更改分区压缩设置时重新生成所有分区。

  • REBUILD WITH ( <rebuild_option> )
    为具有聚集索引的表应用所有选项。如果表没有聚集索引,则只有部分选项会影响堆结构。

    有关重新生成选项的完整说明,请参阅 index_option (Transact-SQL)

  • DATA_COMPRESSION
    为指定的表、分区号或分区范围指定数据压缩选项。选项如下所示:

    • NONE
      不压缩表或指定的分区。

    • ROW
      使用行压缩来压缩表或指定的分区。

    • PAGE
      使用页压缩来压缩表或指定的分区。

    若要同时重新生成多个分区,请参阅 index_option (Transact-SQL)。如果表没有聚集索引,则更改数据压缩会重新生成堆和非聚集索引。有关压缩的详细信息,请参阅创建压缩表和索引

  • column_set_name XML COLUMN_SET FOR ALL_SPARSE_COLUMNS
    列集的名称。列集是一种非类型化的 XML 表示形式,它将表的所有稀疏列合并为一种结构化的输出。如果某个表包含稀疏列,则不能向该表添加列集。有关列集的详细信息,请参阅使用列集

注释

若要添加新数据行,请使用 INSERT。若要删除数据行,请使用 DELETETRUNCATE TABLE。若要更改现有行中的值,请使用 UPDATE

如果过程缓存中存在引用表的执行计划,ALTER TABLE 会将这些执行计划标记为下次执行时重新编译。

更改列的大小

可以通过在 ALTER COLUMN 子句中指定列数据类型的新大小来更改列的长度、精度或小数位数。如果列中存在数据,则新大小不能小于数据的最大大小。此外,不能在某个索引中定义该列,除非该列的数据类型为 varchar、nvarchar 或 varbinary 并且该索引不是 PRIMARY KEY 约束的结果。请参见示例 P。

锁和 ALTER TABLE

ALTER TABLE 语句指定的更改将立即实现。如果这些更改需要修改表中的行,ALTER TABLE 将更新这些行。ALTER TABLE 将获取表上的架构来修改锁,以确保在更改期间没有其他连接引用(甚至是该表上的元数据,也不引用),但可在结束时执行需要一个极短的 SCH-M 锁的联机索引操作。ALTER TABLE…SWITCH 操作中,源表和目标表都需要锁。对表进行的更改将记录于日志中,并且可以完整恢复。影响超大型表中所有行的更改,比如删除列或者用默认值添加 NOT NULL 列,可能需要较长时间才能完成,并将生成大量日志记录。如同影响许多行的 INSERT、UPDATE 或者 DELETE 语句一样,应谨慎执行这些 ALTER TABLE 语句。

并行计划执行

在 SQL Server 2008 Enterprise 中,根据 max degree of parallelism 配置选项和当前工作负荷,确定运行单个 ALTER TABLE ADD(基于索引)CONSTRAINT 或 DROP(聚集索引)CONSTRAINT 语句采用的处理器数。如果数据库引擎检测到系统正忙,则在语句执行开始之前将自动降低操作并行度。可以通过指定 MAXDOP 选项,手动配置用于运行此语句的处理器数。

已分区表

除了执行涉及到已分区表的 SWITCH 操作外,ALTER TABLE 还可用于更改已分区表的列、约束和触发器的状态,就像它用于非分区表一样。但是,该语句不能用于更改表本身进行分区的方式。若要对已分区表进行重新分区,请使用 ALTER PARTITION SCHEMEALTER PARTITION FUNCTION。此外,不能更改已分区表中列的数据类型。

对包含架构绑定视图的表的限制

应用于包含架构绑定视图的表的 ALTER TABLE 语句的限制,与当前修改包含简单索引的表时应用的限制相同。允许添加列。但是,不允许删除或更改参与任何架构绑定视图的列。如果 ALTER TABLE 语句要求更改用于架构绑定视图中的列,ALTER TABLE 将失败,并且数据库引擎将引发错误消息。有关架构绑定和索引视图的详细信息,请参阅 CREATE VIEW (Transact-SQL)

创建引用表的架构绑定视图不会影响为基表添加或删除触发器。

索引和 ALTER TABLE

删除约束时,作为约束的一部分而创建的索引也将被删除。由 CREATE INDEX 创建的索引必须使用 DROP INDEX 删除。ALTER INDEX 语句可用于重新生成约束定义的索引部分;而不必再使用 ALTER TABLE 来删除和添加约束。

必须删除所有基于列的索引和约束后,才能删除列。

如果删除了创建聚集索引的约束,则存储在聚集索引叶级别的数据行将存储在非聚集表中。通过指定 MOVE TO 选项,可以在单个事务中删除聚集索引并将生成的表移动到另一个文件组或分区方案。MOVE TO 选项有以下限制:

  • MOVE TO 对索引视图或非聚集索引无效。

  • 分区方案或文件组必须已经存在。

  • 如果没有指定 MOVE TO,则表将位于为聚集索引定义的同一分区方案或文件组中。

删除聚集索引时,可以指定 ONLINE = ON 选项,这样 DROP INDEX 事务就不会阻塞对基础数据和相关的非聚集索引的查询和修改。

ONLINE = ON 具有下列限制:

  • ONLINE = ON 对于也被禁用的聚集索引无效。必须使用 ONLINE = OFF 删除禁用的索引。

  • 一次只能删除一个索引。

  • ONLINE = ON 对于索引视图、非聚集索引或本地临时表的索引无效。

删除聚集索引时,需要大小等于现有聚集索引的大小的临时磁盘空间。操作完成后,即可释放此额外空间。

注意注意

<drop_clustered_constraint_option> 中列出的选项可适用于表的聚集索引,但不能用于视图的聚集索引或非聚集索引。

复制架构更改

默认情况下,当在 SQL Server 发布服务器中对发布的表运行 ALTER TABLE 时,此更改将传播到所有 SQL Server 订阅服务器。此功能存在一些限制并可禁用。有关详细信息,请参阅对发布数据库进行架构更改

数据压缩

不能为系统表启用压缩功能。如果表是堆,ONLINE 模式的重新生成操作将在单个线程内完成。请为多线程堆重新生成操作使用 OFFLINE 模式。有关数据压缩的详细信息,请参阅创建压缩表和索引

若要评估更改压缩状态将对表、索引或分区有何影响,请使用 sp_estimate_data_compression_savings 存储过程。

以下限制适用于已分区表:

  • 如果表具有非对齐索引,则无法更改单个分区的压缩设置。

  • ALTER TABLE <table> REBUILD PARTITION ... 语法可重新生成指定分区。

  • ALTER TABLE <table> REBUILD WITH ... 语法可重新生成所有分区。

权限

需要对表的 ALTER 权限。

ALTER TABLE 权限适用于 ALTER TABLE SWITCH 语句涉及的两个表。任何已切换的数据都将继承目标表的安全性。

如果将 ALTER TABLE 语句中的任何列定义为公共语言运行时 (CLR) 用户定义类型或别名数据类型,都需要对该类型有 REFERENCES 权限。

示例

A. 添加新列

以下示例将添加一个允许空值的列,而且没有通过 DEFAULT 定义提供的值。在该新列中,每一行都将有 NULL 值。

CREATE TABLE dbo.doc_exa (column_a INT) ;
GO
ALTER TABLE dbo.doc_exa ADD column_b VARCHAR(20) NULL ;
GO
EXEC sp_help doc_exa ;
GO
DROP TABLE dbo.doc_exa ;
GO

B. 删除列

以下示例将修改一个表以删除列。

CREATE TABLE dbo.doc_exb (column_a INT, column_b VARCHAR(20) NULL) ;
GO
ALTER TABLE dbo.doc_exb DROP COLUMN column_b ;
GO
EXEC sp_help doc_exb ;
GO
DROP TABLE dbo.doc_exb ;
GO

C. 更改列的数据类型

以下示例将表中列的数据类型由 INT 改为 DECIMAL。

CREATE TABLE dbo.doc_exy (column_a INT ) ;
GO
INSERT INTO dbo.doc_exy (column_a) VALUES (10) ;
GO
ALTER TABLE dbo.doc_exy ALTER COLUMN column_a DECIMAL (5, 2) ;
GO
DROP TABLE dbo.doc_exy ;
GO

D. 添加包含约束的列

以下示例将添加一个包含 UNIQUE 约束的新列。

CREATE TABLE dbo.doc_exc (column_a INT) ;
GO
ALTER TABLE dbo.doc_exc ADD column_b VARCHAR(20) NULL 
    CONSTRAINT exb_unique UNIQUE ;
GO
EXEC sp_help doc_exc ;
GO
DROP TABLE dbo.doc_exc ;
GO

E. 在现有列中添加一个未经验证的 CHECK 约束

以下示例将在表中的现有列中添加一个约束。该列包含一个违反约束的值。因此,将使用 WITH NOCHECK 以避免根据现有行验证该约束,从而允许添加该约束。

CREATE TABLE dbo.doc_exd ( column_a INT) ;
GO
INSERT INTO dbo.doc_exd VALUES (-1) ;
GO
ALTER TABLE dbo.doc_exd WITH NOCHECK 
ADD CONSTRAINT exd_check CHECK (column_a > 1) ;
GO
EXEC sp_help doc_exd ;
GO
DROP TABLE dbo.doc_exd ;
GO

F. 在现有列中添加一个 DEFAULT 约束

以下示例将创建一个包含两列的表,在第一列插入一个值,另一列保持为 NULL。然后在第二列中添加一个 DEFAULT 约束。验证是否已应用了默认值,另一个值是否已插入第一列以及是否已查询表。

CREATE TABLE dbo.doc_exz ( column_a INT, column_b INT) ;
GO
INSERT INTO dbo.doc_exz (column_a)VALUES ( 7 ) ;
GO
ALTER TABLE dbo.doc_exz
ADD CONSTRAINT col_b_def
DEFAULT 50 FOR column_b ;
GO
INSERT INTO dbo.doc_exz (column_a) VALUES ( 10 ) ;
GO
SELECT * FROM dbo.doc_exz ;
GO
DROP TABLE dbo.doc_exz ;
GO

G. 添加多个包含约束的列

以下示例将添加多个包含随新列定义的约束的列。第一个新列具有 IDENTITY 属性。表中的每一行在标识列中都有新的增量值。

CREATE TABLE dbo.doc_exe ( column_a INT CONSTRAINT column_a_un UNIQUE) ;
GO
ALTER TABLE dbo.doc_exe ADD 

-- Add a PRIMARY KEY identity column.
column_b INT IDENTITY
CONSTRAINT column_b_pk PRIMARY KEY, 

-- Add a column that references another column in the same table.
column_c INT NULL  
CONSTRAINT column_c_fk 
REFERENCES doc_exe(column_a),

-- Add a column with a constraint to enforce that 
-- nonnull data is in a valid telephone number format.
column_d VARCHAR(16) NULL 
CONSTRAINT column_d_chk
CHECK 
(column_d LIKE '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]' OR
column_d LIKE
'([0-9][0-9][0-9]) [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]'),

-- Add a nonnull column with a default.
column_e DECIMAL(3,3)
CONSTRAINT column_e_default
DEFAULT .081 ;
GO
EXEC sp_help doc_exe ;
GO
DROP TABLE dbo.doc_exe ;
GO

H. 添加包含默认值的可为空的列

以下示例将添加一个包含 DEFAULT 定义的可为空的列,并使用 WITH VALUES 为表中的各个现有行提供值。如果没有使用 WITH VALUES,那么每一行的新列中都将具包含 NULL 值。

USE AdventureWorks ; 
GO
CREATE TABLE dbo.doc_exf ( column_a INT) ;
GO
INSERT INTO dbo.doc_exf VALUES (1) ;
GO
ALTER TABLE dbo.doc_exf 
ADD AddDate smalldatetime NULL
CONSTRAINT AddDateDflt
DEFAULT GETDATE() WITH VALUES ;
GO
DROP TABLE dbo.doc_exf ;
GO

I. 禁用和重新启用约束

以下示例禁用对数据中接受的薪金进行限制的约束。NOCHECK CONSTRAINT 将与 ALTER TABLE 配合使用来禁用该约束,从而允许执行通常会违反该约束的插入操作。CHECK CONSTRAINT 将重新启用该约束。

CREATE TABLE dbo.cnst_example 
(id INT NOT NULL,
 name VARCHAR(10) NOT NULL,
 salary MONEY NOT NULL
    CONSTRAINT salary_cap CHECK (salary < 100000)
);

-- Valid inserts
INSERT INTO dbo.cnst_example VALUES (1,'Joe Brown',65000);
INSERT INTO dbo.cnst_example VALUES (2,'Mary Smith',75000);

-- This insert violates the constraint.
INSERT INTO dbo.cnst_example VALUES (3,'Pat Jones',105000);

-- Disable the constraint and try again.
ALTER TABLE dbo.cnst_example NOCHECK CONSTRAINT salary_cap;
INSERT INTO dbo.cnst_example VALUES (3,'Pat Jones',105000);

-- Re-enable the constraint and try another insert; this will fail.
ALTER TABLE dbo.cnst_example CHECK CONSTRAINT salary_cap;
INSERT INTO dbo.cnst_example VALUES (4,'Eric James',110000) ;

J. 删除约束

以下示例将从表中删除 UNIQUE 约束。

CREATE TABLE dbo.doc_exc ( column_a INT
CONSTRAINT my_constraint UNIQUE) ;
GO
ALTER TABLE dbo.doc_exc DROP CONSTRAINT my_constraint ;
GO
DROP TABLE dbo.doc_exc ;
GO

K. 在表之间切换分区

以下示例创建一个已分区表,并假定在数据库中已经创建了分区方案 myRangePS1。然后,在 PartitionTable 表的 PARTITION 2 所在的同一文件组中,创建与已分区表结构相同的未分区的表。最后,将 PartitionTable 表的 PARTITION 2 中的数据切换到 NonPartitionTable 表中。

CREATE TABLE PartitionTable (col1 int, col2 char(10))
ON myRangePS1 (col1) ;
GO
CREATE TABLE NonPartitionTable (col1 int, col2 char(10))
ON test2fg ;
GO
ALTER TABLE PartitionTable SWITCH PARTITION 2 TO NonPartitionTable ;
GO

L. 禁用和重新启用触发器

以下示例将使用 ALTER TABLE 的 DISABLE TRIGGER 选项来禁用触发器,以允许执行通常会违反此触发器的插入操作。然后,使用 ENABLE TRIGGER 重新启用触发器。

CREATE TABLE dbo.trig_example 
(id INT, 
name VARCHAR(12),
salary MONEY) ;
GO
-- Create the trigger.
CREATE TRIGGER dbo.trig1 ON dbo.trig_example FOR INSERT
AS
IF (SELECT COUNT(*) FROM INSERTED
WHERE salary > 100000) > 0
BEGIN
    print 'TRIG1 Error: you attempted to insert a salary > $100,000'
    ROLLBACK TRANSACTION
END ;
GO
-- Try an insert that violates the trigger.
INSERT INTO dbo.trig_example VALUES (1,'Pat Smith',100001) ;
GO
-- Disable the trigger.
ALTER TABLE dbo.trig_example DISABLE TRIGGER trig1 ;
GO
-- Try an insert that would typically violate the trigger.
INSERT INTO dbo.trig_example VALUES (2,'Chuck Jones',100001) ;
GO
-- Re-enable the trigger.
ALTER TABLE dbo.trig_example ENABLE TRIGGER trig1 ;
GO
-- Try an insert that violates the trigger.
INSERT INTO dbo.trig_example VALUES (3,'Mary Booth',100001) ;
GO

M. 创建包含索引选项的 PRIMARY KEY 约束

下面的示例将创建 PRIMARY KEY 约束 PK_TransactionHistoryArchive_TransactionID,并设置 FILLFACTOR、ONLINE 和 PAD_INDEX 选项。生成的聚集索引将与约束同名。

USE AdventureWorks;
GO
ALTER TABLE Production.TransactionHistoryArchive WITH NOCHECK 
ADD CONSTRAINT PK_TransactionHistoryArchive_TransactionID PRIMARY KEY CLUSTERED (TransactionID)
WITH (FILLFACTOR = 75, ONLINE = ON, PAD_INDEX = ON)
GO

N. 在 ONLINE 模式下删除 PRIMARY KEY 约束

下面的示例在 ONLINE 选项设置为 ON 的情况下删除 PRIMARY KEY 约束。

USE AdventureWorks;
GO
ALTER TABLE Production.TransactionHistoryArchive
DROP CONSTRAINT PK_TransactionHistoryArchive_TransactionID
WITH (ONLINE = ON);
GO

O. 添加和删除 FOREIGN KEY 约束

以下示例将创建 ContactBackup 表,然后更改此表。首先添加引用 Contact 表的 FOREIGN KEY 约束,然后再删除 FOREIGN KEY 约束。

USE AdventureWorks ;
GO
CREATE TABLE Person.ContactBackup
(ContactID int) ;
GO
ALTER TABLE Person.ContactBackup
ADD CONSTRAINT FK_ContactBacup_Contact FOREIGN KEY (ContactID)
    REFERENCES Person.Contact (ContactID) ;
ALTER TABLE Person.ContactBackup
DROP CONSTRAINT FK_ContactBacup_Contact ;
GO
DROP TABLE Person.ContactBackup ;

P.更改列的大小

下面的示例增加 varchar 列的大小和 decimal 列的精度和小数位数。因为列包含数据,所以只能增加列的大小。此外,请注意:col_a 是在一个唯一索引中定义的。仍然可以增加 col_a 的大小,因为其数据类型为 varchar 并且该索引不是 PRIMARY KEY 约束的结果。

IF OBJECT_ID ( 'dbo.doc_exy', 'U' ) IS NOT NULL 
    DROP TABLE dbo.doc_exy;
GO
-- Create a two-column table with a unique index on the varchar column.
CREATE TABLE dbo.doc_exy ( col_a varchar(5) UNIQUE NOT NULL, col_b decimal (4,2));
GO
INSERT INTO dbo.doc_exy VALUES ('Test', 99.99);
GO
-- Verify the current column size.
SELECT name, TYPE_NAME(system_type_id), max_length, precision, scale
FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.doc_exy');
GO
-- Increase the size of the varchar column.
ALTER TABLE dbo.doc_exy ALTER COLUMN col_a varchar(25);
GO
-- Increase the scale and precision of the decimal column.
ALTER TABLE dbo.doc_exy ALTER COLUMN col_b decimal (10,4);
GO
-- Insert a new row.
INSERT INTO dbo.doc_exy VALUES ('MyNewColumnSize', 99999.9999) ;
GO
-- Verify the current column size.
SELECT name, TYPE_NAME(system_type_id), max_length, precision, scale
FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.doc_exy');

Q. 允许已分区表中的锁升级

以下示例在已分区表的分区级别启用锁升级。如果该表未分区,则会将锁升级到 TABLE 级别。

ALTER TABLE T1 SET (LOCK_ESCALATION = AUTO)
GO

R. 配置表的更改跟踪

下面的示例启用 AdventureWorks 数据库中 Person.Contact 表的更改跟踪。

USE AdventureWorks;
ALTER TABLE Person.Contact
ENABLE CHANGE_TRACKING;

下面的示例启用更改跟踪,并启用在进行某项更改期间会进行更新的列的跟踪。

USE AdventureWorks;
ALTER TABLE Person.Contact
ENABLE CHANGE_TRACKING
WITH (TRACK_COLUMNS_UPDATED = ON);

下面的示例禁用 AdventureWorks 数据库中 Person.Contact 表的更改跟踪。

USE AdventureWorks;
ALTER TABLE Person.Contact
DISABLE CHANGE_TRACKING;

S. 修改表以更改压缩

下面的示例更改未分区表的压缩。将会重新生成堆或聚集索引。如果表是一个堆,将重新生成所有非聚集索引。

ALTER TABLE T1 
REBUILD WITH (DATA_COMPRESSION = PAGE);

下面的示例更改已分区表的压缩。REBUILD PARTITION = 1 语法仅仅导致重新生成编号为 1 的分区。

ALTER TABLE PartitionTable1 
REBUILD PARTITION = 1 WITH (DATA_COMPRESSION =  NONE) ;
GO

使用以下替代语法的相同操作则会导致重新生成表中的所有分区。

ALTER TABLE PartitionTable1 
REBUILD PARTITION ALL 
WITH (DATA_COMPRESSION = PAGE ON PARTITIONS(1) ) ;

有关其他数据压缩示例,请参阅创建压缩表和索引

T. 添加稀疏列

下面的示例演示如何在表 T1 中添加和修改稀疏列。创建表 T1 的代码如下所示。

CREATE TABLE T1
(C1 int PRIMARY KEY,
C2 varchar(50) SPARSE NULL,
C3 int SPARSE NULL,
C4 int ) ;
GO

若要添加另一个稀疏列 C5,请执行以下语句。

ALTER TABLE T1
ADD C5 char(100) SPARSE NULL ;
GO

若要将 C4 非稀疏列转换为稀疏列,请执行以下语句。

ALTER TABLE T1
ALTER COLUMN C4 ADD SPARSE ;
GO

若要将 C4 稀疏列转换为非稀疏列,请执行以下语句。

ALTER TABLE T1
ALTER COLUMN C4 DROP SPARSE;
GO

U. 添加列集

以下示例演示如何向表 T2 中添加一列。如果表已包含稀疏列,则不能向该表添加列集。创建表 T2 的代码如下所示。

CREATE TABLE T2
(C1 int PRIMARY KEY,
C2 varchar(50) NULL,
C3 int NULL,
C4 int ) ;
GO

下面的三个语句添加名为 CS 的列集,然后将列 C2 和 C3 修改为 SPARSE。

ALTER TABLE T2
ADD CS XML COLUMN_SET FOR ALL_SPARSE_COLUMNS ;
GO

ALTER TABLE T2
ALTER COLUMN C2 ADD SPARSE ; 
GO

ALTER TABLE T2
ALTER COLUMN C3 ADD SPARSE ;
GO

V. 更改排序规则

下面的示例说明了如何更改列的排序规则。首先,我们创建表 T3 以及默认的用户排序规则:

CREATE TABLE T3
(C1 int PRIMARY KEY,
C2 varchar(50) NULL,
C3 int NULL,
C4 int ) ;
GO

接着,将列 C2 排序规则更改为 Latin1_General_BIN。请注意,需要数据类型,即使排序规则未更改也不例外。

ALTER TABLE T3
ALTER COLUMN C2 varchar(50) COLLATE Latin1_General_BIN 
GO

文档更改历史记录

更新的内容

固定了锁升级 AUTO 选项。

在语法属性中添加了 [ SPARSE ](在 [ NULL | NOT NULL ] 之前)。

在“参数”部分添加了有关 UDT、默认值以及为 Null 性的信息。

在“参数”部分的 SPARSE 语法定义中添加了其他信息。

添加了一个示例,说明如何更改列排序规则和重新指定数据类型的要求。