ALTER TABLE (Transact-SQL)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse Analytics分析平台系统 (PDW)Microsoft Fabric 中的仓库Microsoft Fabric 预览版中的 SQL 数据库

通过更改、添加或删除列和约束,修改表定义。 ALTER TABLE 还可以重新分配和重新生成分区,或者禁用并启用约束和触发器。

Note

目前, ALTER TABLE Fabric Warehouse 中仅支持约束和添加可以为 null 的列。 请参阅 Microsoft Fabric 中仓库的语法。 目前,内存优化表在 Microsoft Fabric 预览版的 SQL 数据库中不可用。

基于磁盘的表和内存优化表的语法 ALTER TABLE 不同。 使用以下链接可以直接跳至适用于表类型的语法块和相应的语法示例:

基于磁盘的表:

内存优化表:

有关语法约定的详细信息,请参阅 Transact-SQL 语法约定

基于磁盘的表的语法

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

    | ADD
    {
        <column_definition>
      | <computed_column_definition>
      | <table_constraint>
      | <column_set_definition>
    } [ ,...n ]
      | [ system_start_time_column_name datetime2 GENERATED ALWAYS AS ROW START
                [ HIDDEN ] [ NOT NULL ] [ CONSTRAINT constraint_name ]
            DEFAULT constant_expression [WITH VALUES] ,
                system_end_time_column_name datetime2 GENERATED ALWAYS AS ROW END
                   [ HIDDEN ] [ NOT NULL ][ CONSTRAINT constraint_name ]
            DEFAULT constant_expression [WITH VALUES] ,
                start_transaction_id_column_name bigint GENERATED ALWAYS AS TRANSACTION_ID START
                   [ HIDDEN ] NOT NULL [ CONSTRAINT constraint_name ]
            DEFAULT constant_expression [WITH VALUES],
                  end_transaction_id_column_name bigint GENERATED ALWAYS AS TRANSACTION_ID END
                   [ HIDDEN ] NULL [ CONSTRAINT constraint_name ]
            DEFAULT constant_expression [WITH VALUES],
                  start_sequence_number_column_name bigint GENERATED ALWAYS AS SEQUENCE_NUMBER START
                   [ HIDDEN ] NOT NULL [ CONSTRAINT constraint_name ]
            DEFAULT constant_expression [WITH VALUES],
                  end_sequence_number_column_name bigint GENERATED ALWAYS AS SEQUENCE_NUMBER END
                   [ HIDDEN ] NULL [ CONSTRAINT constraint_name ]
            DEFAULT constant_expression [WITH VALUES]
        ]
       PERIOD FOR SYSTEM_TIME ( system_start_time_column_name, system_end_time_column_name )
    | DROP
     [ {
         [ CONSTRAINT ][ IF EXISTS ]
         {
              constraint_name
              [ WITH
               ( <drop_clustered_constraint_option> [ ,...n ] )
              ]
          } [ ,...n ]
          | COLUMN [ IF EXISTS ]
          {
              column_name
          } [ ,...n ]
          | PERIOD FOR SYSTEM_TIME
     } [ ,...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 ]
        [ WITH ( <low_priority_lock_wait> ) ]

    | SET
        (
            [ FILESTREAM_ON =
                { partition_scheme_name | filegroup | "default" | "NULL" } ]
            | SYSTEM_VERSIONING =
                  {
                    OFF
                  | ON
                      [ ( HISTORY_TABLE = schema_name . history_table_name
                          [, DATA_CONSISTENCY_CHECK = { ON | OFF } ]
                          [, HISTORY_RETENTION_PERIOD =
                          {
                              INFINITE | number {DAY | DAYS | WEEK | WEEKS
                  | MONTH | MONTHS | YEAR | YEARS }
                          }
                          ]
                        )
                      ]
                  }
            | DATA_DELETION =
                {
                      OFF
                    | ON
                        [(  [ FILTER_COLUMN = column_name ]
                            [, RETENTION_PERIOD = { INFINITE | number { DAY | DAYS | WEEK | WEEKS
                                    | MONTH | MONTHS | YEAR | YEARS } } ]
                        )]
                    } )
    | REBUILD
      [ [PARTITION = ALL]
        [ WITH ( <rebuild_option> [ ,...n ] ) ]
      | [ PARTITION = partition_number
           [ WITH ( <single_partition_rebuild_option> [ ,...n ] ) ]
        ]
      ]

    | <table_option>
    | <filetable_option>
    | <stretch_configuration>
}
[ ; ]

-- ALTER TABLE options

<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 } )
    }

<filetable_option> ::=
    {
       [ { ENABLE | DISABLE } FILETABLE_NAMESPACE ]
       [ SET ( FILETABLE_DIRECTORY = directory_name ) ]
    }

<stretch_configuration> ::=
    {
      SET (
        REMOTE_DATA_ARCHIVE
        {
            = ON (<table_stretch_options>)
          | = OFF_WITHOUT_DATA_RECOVERY ( MIGRATION_STATE = PAUSED )
          | ( <table_stretch_options> [, ...n] )
        }
            )
    }

<table_stretch_options> ::=
    {
     [ FILTER_PREDICATE = { null | table_predicate_function } , ]
       MIGRATION_STATE = { OUTBOUND | INBOUND | PAUSED }
    }

<single_partition_rebuild__option> ::=
{
      SORT_IN_TEMPDB = { ON | OFF }
    | MAXDOP = max_degree_of_parallelism
    | DATA_COMPRESSION = { NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE}
    | ONLINE = { ON [( <low_priority_lock_wait> ) ] | OFF }
}

<low_priority_lock_wait>::=
{
    WAIT_AT_LOW_PRIORITY ( MAX_DURATION = <time> [ MINUTES ],
        ABORT_AFTER_WAIT = { NONE | SELF | BLOCKERS } )
}

有关详细信息,请参阅:

内存优化表的语法

ALTER TABLE { database_name.schema_name.table_name | schema_name.table_name | table_name }
{
    ALTER COLUMN column_name
    {
        [ type_schema_name. ] type_name
            [ (
                {
                   precision [ , scale ]
                }
            ) ]
        [ COLLATE collation_name ]
        [ NULL | NOT NULL ]
    }

    | ALTER INDEX index_name
    {
        [ type_schema_name. ] type_name
        REBUILD
        [ [ NONCLUSTERED ] WITH ( BUCKET_COUNT = bucket_count )
        ]
    }

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

    | DROP
     [ {
         CONSTRAINT [ IF EXISTS ]
         {
              constraint_name
          } [ ,...n ]
        | INDEX [ IF EXISTS ]
      {
         index_name
       } [ ,...n ]
          | COLUMN [ IF EXISTS ]
          {
              column_name
          } [ ,...n ]
          | PERIOD FOR SYSTEM_TIME
     } [ ,...n ] ]
    | [ WITH { CHECK | NOCHECK } ] { CHECK | NOCHECK } CONSTRAINT
        { ALL | constraint_name [ ,...n ] }

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

    | SWITCH [ [ PARTITION ] source_partition_number_expression ]
        TO target_table
        [ PARTITION target_partition_number_expression ]
        [ WITH ( <low_priority_lock_wait> ) ]

}
[ ; ]

-- ALTER TABLE options

< table_constraint > ::=
 [ CONSTRAINT constraint_name ]
{
   {PRIMARY KEY | UNIQUE }
     {
       NONCLUSTERED (column [ ASC | DESC ] [ ,... n ])
       | NONCLUSTERED HASH (column [ ,... n ] ) WITH ( BUCKET_COUNT = bucket_count )
     }
    | FOREIGN KEY
        ( column [ ,...n ] )
        REFERENCES referenced_table_name [ ( ref_column [ ,...n ] ) ]
    | CHECK ( logical_expression )
}

<column_index> ::=
  INDEX index_name
{ [ NONCLUSTERED ] | [ NONCLUSTERED ] HASH WITH (BUCKET_COUNT = bucket_count) }

<table_index> ::=
  INDEX index_name
{ [ NONCLUSTERED ] HASH (column [ ,... n ] ) WITH (BUCKET_COUNT = bucket_count)
  | [ NONCLUSTERED ] (column [ ASC | DESC ] [ ,... n ] )
      [ ON filegroup_name | default ]
  | CLUSTERED COLUMNSTORE [ WITH ( COMPRESSION_DELAY = { 0 | delay [MINUTES] } ) ]
      [ ON filegroup_name | default ]
}

Azure Synapse Analytics 和并行数据仓库的语法

ALTER TABLE { database_name.schema_name.source_table_name | schema_name.source_table_name | source_table_name }
{
    ALTER COLUMN column_name
        {
            type_name [ ( precision [ , scale ] ) ]
            [ COLLATE Windows_collation_name ]
            [ NULL | NOT NULL ]
        }
    | ADD { <column_definition> | <column_constraint> FOR column_name} [ ,...n ]
    | DROP { COLUMN column_name | [CONSTRAINT] constraint_name } [ ,...n ]
    | REBUILD {
            [ PARTITION = ALL [ WITH ( <rebuild_option> ) ] ]
          | [ PARTITION = partition_number [ WITH ( <single_partition_rebuild_option> ] ]
      }
    | { SPLIT | MERGE } RANGE (boundary_value)
    | SWITCH [ PARTITION source_partition_number
        TO target_table_name [ PARTITION target_partition_number ] [ WITH ( TRUNCATE_TARGET = ON | OFF ) ] ]
}
[ ; ]

<column_definition>::=
{
    column_name
    type_name [ ( precision [ , scale ] ) ]
    [ <column_constraint> ]
    [ COLLATE Windows_collation_name ]
    [ NULL | NOT NULL ]
}

<column_constraint>::=
    [ CONSTRAINT constraint_name ]
    {
        DEFAULT constant_expression
        | PRIMARY KEY NONCLUSTERED (column_name [ ,... n ]) NOT ENFORCED -- Applies to Azure Synapse Analytics only
        | UNIQUE (column_name [ ,... n ]) NOT ENFORCED -- Applies to Azure Synapse Analytics only
    }
<rebuild_option > ::=
{
    DATA_COMPRESSION = { COLUMNSTORE | COLUMNSTORE_ARCHIVE }
        [ ON PARTITIONS ( {<partition_number> [ TO <partition_number>] } [ , ...n ] ) ]
    | XML_COMPRESSION = { ON | OFF }
        [ ON PARTITIONS ( {<partition_number> [ TO <partition_number>] } [ , ...n ] ) ]
}

<single_partition_rebuild_option > ::=
{
    DATA_COMPRESSION = { COLUMNSTORE | COLUMNSTORE_ARCHIVE }
}

Note

Azure Synapse 分析中的无服务器 SQL 池仅支持外部表和临时表。

Fabric 中仓库的语法

ALTER TABLE { database_name.schema_name.table_name | schema_name.table_name | table_name }
{
  ADD  { column_name <data_type> [COLLATE collation_name] [ <column_options> ] } [ ,...n ]
| ADD { <column_constraint> FOR column_name} [ ,...n ]
| DROP { COLUMN column_name | [CONSTRAINT] constraint_name } [ ,...n ]
}
[ ; ]

<column_options> ::=
[ NULL ] -- default is NULL

<data type> ::=
datetime2 ( n )
| date
| time ( n )
| float [ ( n ) ]
| real [ ( n ) ]
| decimal [ ( precision [ , scale ] ) ]
| numeric [ ( precision [ , scale ] ) ]
| bigint
| int
| smallint
| bit
| varchar [ ( n ) ]
| char [ ( n ) ]
| varbinary [ ( n ) ]
| uniqueidentifier

<column_constraint>::=
    [ CONSTRAINT constraint_name ]
    {
       PRIMARY KEY NONCLUSTERED (column_name [ ,... n ]) NOT ENFORCED
        | UNIQUE NONCLUSTERED (column_name [ ,... n ]) NOT ENFORCED
    | FOREIGN KEY
        ( column [ ,...n ] )
        REFERENCES referenced_table_name [ ( ref_column [ ,...n ] ) ] NOT ENFORCED
    }

Arguments

database_name

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

schema_name

表所属的架构的名称。

table_name

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

ALTER COLUMN

指定要更改的命名列。

修改后的列不得为:

  • 数据类型为 timestamp 的列。

  • ROWGUIDCOL 的编号。

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

  • 用于语句生成的 CREATE STATISTICS 统计信息。 用户需要运行 DROP STATISTICS 才能删除统计信息,然后 ALTER COLUMN 才能成功。 运行此查询以获取用户创建的所有统计信息和表的统计信息列。

    SELECT s.name AS statistics_name,
           c.name AS column_name,
           sc.stats_column_id
    FROM sys.stats AS s
         INNER JOIN sys.stats_columns AS sc
             ON s.object_id = sc.object_id
            AND s.stats_id = sc.stats_id
         INNER JOIN sys.columns AS c
             ON sc.object_id = c.object_id
            AND c.column_id = sc.column_id
    WHERE s.object_id = OBJECT_ID('<table_name>');
    

    Note

    查询优化器自动生成的统计信息将自动删除 ALTER COLUMN

  • 在约束[FOREIGN KEY] REFERENCES中使用PRIMARY KEY

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

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

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

  • text 更改为 varchar(max)、nvarchar(max) 或 xml
  • ntext 更改为 varchar(max)、nvarchar(max) 或 xml
  • image 更改为 varbinary(max)

某些数据类型更改可能会导致数据发生更改。 例如,将 nchar 或 nvarchar 列更改为 char 或 varchar 可能会导致转换扩展字符。 有关详细信息,请参阅 CAST 和 CONVERT。 减少列的精度或确定位数可能会导致数据截断。

Note

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

除非列的数据类型为 varchar、nvarchar 或 varbinary,且新大小等于或大于旧大小,否则无法更改索引中所含列的数据类型。

主键约束中包含的列不能从NOT NULLNULL更改为 。

使用 Always Encrypted(没有安全 enclave)时,如果修改的列已使用 ENCRYPTED WITH加密,则可以将数据类型更改为兼容的数据类型(例如 INT ), BIGINT但不能更改任何加密设置。

使用 Always Encrypted(含安全 enclave)时,如果用于保护列的列加密密钥(以及新的列加密密钥,若要更改密钥的话)支持 enclave 计算(使用已启用 enclave 的列主密钥进行加密),就可以更改任何加密设置。 有关详细信息,请参阅具有安全 Enclave 的 Always Encrypted

修改列时,数据库引擎通过添加系统表中的行并将上一列修改标记为已删除列来跟踪每次修改。 在极少数情况下,如果修改列的次数过多,数据库引擎可能会达到记录大小限制。 如果发生这种情况,将收到错误 511 或 1708。 要避免这些错误,请定期重新生成表上的聚集索引,或减少列修改次数。

column_name

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

Note

在更改表中的所有现有列之后,将添加新列。

[ type_schema_name. ] type_name

更改后的列的新数据类型,或添加的列的数据类型。 无法为已分区表的现有列指定 type_name。 type_name 可以是下列任一数据类型:

  • SQL Server 系统数据类型。
  • 基于 SQL Server 系统数据类型的别名数据类型。 使用语句创建别名数据类型 CREATE TYPE ,然后才能在表定义中使用它们。
  • .NET Framework 用户定义类型及其所属架构。 使用语句创建用户定义的类型 CREATE TYPE ,然后才能在表定义中使用它们。

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

  • 以前的数据类型必须可以隐式转换为新数据类型。
  • type_name 不得为 timestamp
  • ANSI_NULL默认值始终为打开; ALTER COLUMN如果未指定,则列可为 null。
  • ANSI_PADDING 填充始终 ON 用于 ALTER COLUMN
  • 如果修改后的列是标识列,则 new_data_type 必须是支持标识属性的数据类型。
  • 忽略当前设置 SET ARITHABORTALTER TABLE 作方式好像 ARITHABORT 设置为 ON.

Note

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

precision

指定的数据类型的精度。 有关有效精度值的详细信息,请参阅 精度、小数位数和长度

scale

指定的数据类型的确定位数。 有关有效刻度值的详细信息,请参阅 精度、小数位数和长度

max

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

xml_schema_collection

适用于:SQL Server 和 Azure SQL 数据库。

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

COLLATE <collation_name>

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

COLLATE句仅更改 charvarchar、ncharnvarchar 数据类型的列的排序规则。 若要更改用户定义的别名数据类型列的排序规则,请使用单独的 ALTER TABLE 语句将列更改为 SQL Server 系统数据类型。 然后,更改它的排序规则,并将列更改回别名数据类型。

ALTER COLUMN 如果存在以下一个或多个条件,则无法进行排序规则更改:

  • CHECK约束、FOREIGN KEY约束或计算列引用列已更改。
  • 在列上创建任何索引、统计信息或全文索引。 如果更改了列的排序规则,则将删除为更改后的列自动创建的统计信息。
  • 架构绑定视图或函数引用列。

有关支持的排序规则的详细信息,请参阅 COLLATE

NULL |NOT NULL

指定列是否可接受空值。 仅当列具有指定的默认值或表为空时,才会添加 ALTER TABLE 不允许为 null 值的列。 仅当还指定了计算列时,才能 NOT NULL 为计算列指定 PERSISTED。 如果新列允许 NULL 值,但没有指定默认定义,那么新列对表中的每一行都包含 NULL 值。 如果新列允许 null 值,并且使用新列添加默认定义,则可以用于 WITH VALUES 将默认值存储在表中每个现有行的新列中。

如果新列不允许 null 值,并且表不为空,则必须使用新列添加 DEFAULT 定义。 另外,每个现有行对应的新列自动加载有默认值。

可以指定NULLALTER COLUMN以强制NOT NULL列允许 null 值,但约束中的PRIMARY KEY列除外。 仅当列不包含 null 值时,才能指定NOT NULLALTER COLUMN。 null 值必须在允许之前 ALTER COLUMNNOT NULL 更新为某些值,例如:

UPDATE MyTable SET NullCol = N'some_value' WHERE NullCol IS NULL;

ALTER TABLE MyTable ALTER COLUMN NullCOl NVARCHAR (20) NOT NULL;

使用或ALTER TABLE语句创建或更改表CREATE TABLE时,数据库和会话设置会影响并可能替代列定义中使用的数据类型的可为 null 性。 请确保始终将列 NULL 显式定义为非计算列或 NOT NULL 非计算列。

如果添加使用用户定义数据类型的列,请务必将列定义为与用户定义数据类型的为 Null 性相同。 此外,指定列的默认值。 有关详细信息,请参阅 CREATE TABLE

Note

如果NULL指定或NOT NULL指定了 ALTER COLUMN,则还必须指定 [(精度 [, 刻度 ])] new_data_type。 如果未更改数据类型、精度和小数位数,请指定当前列值。

[ {ADD |DROP} ROWGUIDCOL ]

适用于:SQL Server 和 Azure SQL 数据库。

指定 ROWGUIDCOL 将属性添加到指定列或从指定列中删除。 ROWGUIDCOL 指示列是行 GUID 列。 每个表只能将一个 uniqueidentifier 列设置为 ROWGUIDCOL 该列。 而且,只能将 ROWGUIDCOL 属性分配给 uniqueidentifier 列。 不能分配给 ROWGUIDCOL 用户定义的数据类型的列。

ROWGUIDCOL 不会强制实施列中存储的值的唯一性,也不会为插入表中的新行自动生成值。 若要为每个列生成唯一值,请使用 NEWID() 语句中的 NEWSEQUENTIALID()INSERT 函数。 或者,将 NEWID()NEWSEQUENTIALID() 函数指定为列的默认值。

[ {ADD |DROP} 持久化 ]

指定 PERSISTED 将属性添加到指定列或从指定列中删除。 列必须是由确定性表达式定义的计算列。 对于指定为 PERSISTED列的列,数据库引擎以物理方式将计算值存储在表中,并在更新计算列所依赖的任何其他列时更新值。 通过将计算列 PERSISTED标记为,可以针对在确定性的表达式上定义的计算列创建索引,但不能精确。 有关详细信息,请参阅 计算列上的索引

SET QUOTED_IDENTIFIER 必须是 ON 在计算列或索引视图上创建或更改索引时。 有关详细信息,请参阅 SET QUOTED_IDENTIFIER

任何用作已分区表分区列的计算列都必须显式标记 PERSISTED

Note

在 Fabric SQL 数据库中,允许计算列,但当前不镜像到 Fabric OneLake。

DROP NOT FOR REPLICATION

适用于:SQL Server 和 Azure SQL 数据库。

指定当复制代理执行插入操作时,标识列中的值递增。 只有当 column_name 是标识列时,才能指定此子句。

SPARSE

指示列为稀疏列。 稀疏列已针对 NULL 值进行了存储优化。 无法将稀疏列设置为 NOT NULL。 将列从稀疏列转换为非稀疏列,或者从非稀疏列转换为稀疏列时,此选项都会导致在命令执行期间锁定表。 可能需要使用 REBUILD 子句来回收任何空间节省。 有关稀疏列的其他限制和详细信息,请参阅 “使用稀疏列”。

添加 MASKED WITH (FUNCTION = 'mask_function')

适用于:SQL Server 2016(13.x)及更高版本以及 Azure SQL 数据库。

指定动态数据掩码。 mask_function 是具有相应参数的掩码函数的名称。 有三个函数可供选择:

  • default()
  • email()
  • partial()
  • random()

ALTER ANY MASK需要权限。

要删除掩码,请使用 DROP MASKED。 有关函数参数,请参阅 动态数据掩码

添加和删除掩码需要 ALTER ANY MASK 权限。

WITH ( ONLINE = ON | OFF) <同样适用于更改某个列>

适用于:SQL Server 2016(13.x)及更高版本以及 Azure SQL 数据库。

允许执行多个更改列操作,同时保持表可用。 默认值为 OFF。 可以联机对列执行与数据类型、列长度或精度、为 Null 性、稀疏性和排序规则相关的列更改。

联机更改列允许用户在作期间创建和自动统计信息引用更改的 ALTER COLUMN 列,从而允许查询照常运行。 在操作结束时,引用列的自动统计信息遭删除,且用户创建的统计信息失效。 完成操作后,用户必须手动更新用户生成的统计信息。 如果列属于任何统计信息或索引的筛选表达式,无法执行更改列操作。

  • 当联机更改列作正在运行时,依赖于该列的任何 DDL作(例如创建或修改索引、视图等)将被阻止,或者失败并出现适当的错误。 此行为可保证联机更改列操作不会由于在执行操作时引入的依赖项而失败。

  • 当更改的列被非聚集索引引用时,不支持将列NOT NULLNULL更改为联机作。

  • 当列由检查约束引用并且ALTER作限制列(数字日期时间)的精度时,不支持联机ALTER

  • WAIT_AT_LOW_PRIORITY 选项无法用于联机更改列。

  • 联机更改列不支持 ALTER COLUMN ... ADD/DROP PERSISTED

  • ALTER COLUMN ... ADD/DROP ROWGUIDCOL/NOT FOR REPLICATION 不受联机更改列影响。

  • 如果已启用更改跟踪或作为合并复制的发布者,联机更改列不支持更改表。

  • 联机更改列不支持更改或更改为 CLR 数据类型。

  • 联机更改列不支持更改为,架构集合不同于当前架构集合的 XML 数据类型。

  • 联机更改列不放宽对可更改列的时间的限制。 索引/统计信息等的引用可能会导致更改失败。

  • 联机更改列不支持同时更改多个列。

  • 联机更改列对经系统版本控制的时态表不起任何作用。 ALTER 列不会联机运行,而不考虑为 ONLINE 选项指定了哪个值。

联机更改列的要求、限制和功能类似于联机索引重新生成,具体包括:

  • 如果表包含旧 LOB 或文件流列,或如果表有列存储索引,不支持联机索引重新生成。 相同的限制也适用于联机更改列。
  • 要更改的现有列需要两倍的空间分配,用于原始列和新创建的隐藏列。
  • 联机更改列操作的锁定策略遵循用于联机索引生成的相同锁定模式。

WITH CHECK |WITH NOCHECK

指定是否根据新添加或重新启用FOREIGN KEYCHECK或约束验证表中的数据。 如果未指定, WITH CHECK 则假定为新约束,并 WITH NOCHECK 假定为重新启用的约束。

如果不想验证针对现有数据的新 CHECKFOREIGN KEY 约束,请使用 WITH NOCHECK。 不建议这样做,极少数情况除外。 新约束在以后的所有数据更新中都会进行评估。 添加约束时禁止 WITH NOCHECK 的任何约束冲突都可能导致将来更新失败(如果更新包含不遵循约束的数据的行)。 查询优化器不考虑定义的 WITH NOCHECK约束。 在使用 ALTER TABLE table WITH CHECK CHECK CONSTRAINT ALL 重新启用这些约束之前,将忽略这些约束。 有关详细信息,请参阅 使用 INSERT 和 UPDATE 语句禁用外键约束

ALTER INDEX index_name

指定要变更或更改 index_name 的桶计数。

仅内存优化表支持语法 ALTER TABLE ... ADD/DROP/ALTER INDEX

Important

如果不使用 ALTER TABLE 语句,内存优化表上的索引不支持 CREATE INDEXDROP INDEXALTER INDEXPAD_INDEX 语句。

ADD

指定添加一个或多个列定义、计算列定义或者表约束。 或者,添加系统用于系统版本控制的列。 对于内存优化表,可以添加索引。

Note

在更改表中的所有现有列之后,将添加新列。

Important

如果不使用 ALTER TABLE 语句,内存优化表上的索引不支持 CREATE INDEXDROP INDEXALTER INDEXPAD_INDEX 语句。

SYSTEM_TIME期(system_start_time_column_name、system_end_time_column_name)

适用于:SQL Server 2017(14.x)及更高版本以及 Azure SQL 数据库。

指定系统用于记录有效记录时间段的列的名称。 可以指定现有列或创建新列作为参数的 ADD PERIOD FOR SYSTEM_TIME 一部分。 使用 datetime2 的数据类型设置列,并将其定义为 NOT NULL。 如果将句点列定义为句点列 NULL,则会出现错误结果。 可以为system_start_time和system_end_time列定义 column_constraint 和/或 指定列的默认值 。 请参阅下面的系统版本控制示例中的示例 A,它展示了如何对 system_end_time 列使用默认值。

将此参数与参数一起使用 SET SYSTEM_VERSIONING ,使现有表成为临时表。 有关详细信息,请参阅 临时表临时表入门

从 SQL Server 2017(14.x)开始,用户可以标记一个或两个句点列,并带有 HIDDEN 标志来隐式隐藏这些列,这样 SELECT * FROM <table_name> 不会返回列的值。 默认情况下,时间段列不处于隐藏状态。 若要使用隐藏的列,则它必须显式包含在直接引用时态表的所有查询中。

DROP

指定删除一个或多个列定义、计算列定义或表约束,或要删除系统用于系统版本控制的列的规范。

Note

在帐本表中删除的列仅被软删除。 删除的列保留在账本表中,但它通过将列设置为dropped_ledger_table删除的列来标记为已删除的列sys.tables1。 已删除账本表的账本视图也通过将 dropped_ledger_view 中的 sys.tables 列设置为 1 来标记为已删除。 通过添加前缀(MSSQL_DroppedLedgerTableMSSQL_DroppedLedgerHistoryMSSQL_DroppedLedgerView)并将 GUID 追加到原始名称来为已删除的账本表、其历史记录表及其账本视图重命名。

CONSTRAINT constraint_name

指定从表中删除 constraint_name。 可以列出多个约束。

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

PRIMARY KEY如果表上存在 XML 索引,则无法删除约束。

INDEX index_name

指定要从表中删除的 index_name

仅内存优化表支持语法 ALTER TABLE ... ADDALTER INDEX/DROP/。

Important

如果不使用 ALTER TABLE 语句,内存优化表上的索引不支持 CREATE INDEXDROP INDEXALTER INDEXPAD_INDEX 语句。

COLUMN column_name

指定从表中删除 constraint_name 或 column_name。 可以列出多个列。

无法删除以下列:

  • 在索引中使用,无论是作为键列还是作为键列 INCLUDE
  • 用于CHECKFOREIGN KEYUNIQUEPRIMARY KEY约束。
  • 与使用关键字定义的 DEFAULT 默认值相关联,或绑定到默认对象。
  • 绑定到规则的列。

Note

删除列并不回收列所占的磁盘空间。 当表的行大小接近或超出其限制时,可能需要回收已删除列的磁盘空间。 通过创建表的聚集索引或使用 ALTER INDEX 重新生成现有的聚集索引,可以回收空间。 有关删除 LOB 数据类型的影响的信息,请参阅此 CSS 博客文章

SYSTEM_TIME期间

适用于:SQL Server 2016(13.x)及更高版本以及 Azure SQL 数据库。

删除系统用于系统版本控制的列的规范。

WITH <drop_clustered_constraint_option>

指定设置一个或多个删除聚集约束选项。

MAXDOP = max_degree_of_parallelism

适用于:SQL Server 和 Azure SQL 数据库。

只在操作期间覆盖 max degree of parallelism 配置选项。 有关详细信息,请参阅 服务器配置:最大并行度

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

max_degree_of_parallelism 可以是下列值之一:

  • 1

    取消生成并行计划。

  • >1

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

  • 0(默认值)

    使用基于当前系统工作负荷的实际处理器数或更少。

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

Note

并行索引操作并不适用于 SQL Server 的所有版本。 有关详细信息,请参阅 SQL Server 2022 的版本及其支持的功能

ONLINE = { ON |OFF } <适用于drop_clustered_constraint_option>

指定在索引操作期间基础表和关联的索引是否可用于查询和数据修改操作。 默认值为 OFF。 可以作为作ONLINE运行REBUILD

  • ON

    长期表锁在索引操作执行期间不保留。 在索引作的主阶段,源表上只保留意向共享 (IS) 锁。 通过此行为,可以继续查询或更新基础表和索引。 在操作开始时,共享 (S) 锁对源对象短时间保留。 在操作结束时,若要创建非聚集索引,便会对源短时间获取 S(共享)锁。 或者,在联机创建或删除聚集索引以及重新生成聚集索引或非聚集索引时,将获取 Sch-M(架构修改)锁。 ONLINE 在本地临时表上创建索引时,无法设置为 ON 该索引。 仅允许单线程堆重新生成操作。

    若要运行 DDL for SWITCH 或联机索引重新生成,必须完成在特定表上运行的所有活动阻塞事务。 执行时, SWITCH 或重新生成作会阻止新事务启动,并且可能会显著影响工作负荷吞吐量,并暂时延迟对基础表的访问。

  • OFF

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

    有关详细信息,请参阅 联机索引作的工作原理

    Note

    联机索引作在 SQL Server 的每个版本中都不可用。 有关详细信息,请参阅 SQL Server 2022 的版本及其支持的功能

MOVE TO { partition_scheme_namecolumn_name [ ,...n ] | | filegroup |“default” }

适用于:SQL Server 和 Azure SQL 数据库。

指定一个位置以移动聚集索引的叶级别中的当前数据行。 表被移至新位置。 此选项仅适用于创建聚集索引的约束。

Note

在此上下文中, default 不是关键字。 它是默认文件组的标识符,必须按 In 或 in MOVE TO "default"MOVE TO [default]. 如果 "default" 已指定,则 QUOTED_IDENTIFIER 选项必须为 ON 当前会话。 这是默认设置。 有关详细信息,请参阅 SET QUOTED_IDENTIFIER

{ CHECK |NOCHECK } 约束

指定启用或禁用 constraint_name。 此选项只能用于 FOREIGN KEY 约束 CHECK 。 指定时 NOCHECK ,将禁用该约束,并且不会根据约束条件验证对列的未来插入或更新。 DEFAULT不能禁用约束PRIMARY KEYUNIQUE

  • ALL

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

{ ENABLE |DISABLE } 触发器

指定启用或禁用 trigger_name。 仍可为表定义禁用的触发器。 但是,在对表运行或DELETEUPDATE语句时INSERT,在重新启用触发器之前,不会执行触发器中的作。

  • ALL

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

  • trigger_name

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

{ ENABLE |DISABLE } CHANGE_TRACKING

适用于:SQL Server 和 Azure SQL 数据库。

指定是启用还是禁用表的更改跟踪。 默认情况下会禁用更改跟踪。

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

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

WITH ( TRACK_COLUMNS_UPDATED = { ON |OFF }

适用于:SQL Server 和 Azure SQL 数据库。

指定 数据库引擎 是否跟踪哪些更改跟踪列已更新。 默认值是 OFF

SWITCH [ PARTITION source_partition_number_expression ] TO [ schema_name. ] target_table [ PARTITION target_partition_number_expression ]

适用于:SQL Server 和 Azure SQL 数据库。

用下列方式之一切换数据块:

  • 将表的所有数据作为分区重新分配给现有的已分区表。
  • 将分区从一个已分区表切换到另一个已分区表。
  • 将已分区表的一个分区中的所有数据重新分配给现有的未分区的表。

如果 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 使用复制时的限制,请参阅 “复制已分区表和索引”。

在版本 V12 之前,以只读格式为 SQL Server 2016 (13.x) 和 SQL 数据库生成非聚集列存储索引。 必须先将非聚集列存储索引重新生成到当前格式(可更新),然后才能运行任何 PARTITION 作。

Limitations

如果两个表都以相同的方式分区,包括非聚集索引,并且目标表没有任何非聚集索引,则可能会收到 4907 错误

示例输出:

Msg 4907, Level 16, State 1, Line 38
'ALTER TABLE SWITCH' statement failed. The table 'MyDB.dbo.PrtTable1' has 4 partitions while index 'MS1' has 6 partitions.

SET ( FILESTREAM_ON = { partition_scheme_name | filestream_filegroup_name |“default” |“NULL” })

适用于:SQL Server。 Azure SQL 数据库 不支持 FILESTREAM

指定 FILESTREAM 数据的存储位置。

ALTER TABLE SET FILESTREAM_ON仅当表没有 FILESTREAM 列时,该子句才会成功。 可以使用第二 ALTER TABLE 个语句添加 FILESTREAM 列。

如果指定 partition_scheme_name,则会应用 CREATE TABLE 规则。 请确保表已针对行数据进行了分区,且它的分区方案使用与 FILESTREAM 分区方案相同的分区功能和分区列。

filestream_filegroup_name 指定 FILESTREAM 文件组的名称。 文件组必须具有一个使用 CREATE DATABASEALTER DATABASE 语句为文件组定义的文件,否则会收到错误。

"default" 指定具有属性集的 DEFAULT FILESTREAM 文件组。 如果没有 FILESTREAM 文件组,则会出现错误。

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

SET ( SYSTEM_VERSIONING = { OFF |ON [ ( HISTORY_TABLE = schema_name . history_table_name [ , DATA_CONSISTENCY_CHECK = { ON |OFF } ] }

适用于:SQL Server 2016(13.x)及更高版本以及 Azure SQL 数据库。

禁用或启用表的系统版本控制。 若要启用表的系统版本控制,系统会验证是否满足系统版本控制的数据类型、可为 null 性约束和主键约束要求。 系统将系统版本控制表中每个记录的历史记录记录记录在单独的历史记录表中。 HISTORY_TABLE如果未使用该参数,则此历史记录表的名称为 MSSQL_TemporalHistoryFor<primary_table_object_id>。 如果不存在历史记录表,系统将生成符合现有表架构的新历史记录表,在两个表之间建立关联,让系统能够在历史记录表中记录当前表中每个记录的历史记录。 如果你使用 HISTORY_TABLE 参数关联到现有历史记录表并使用此表,系统关联当前表和指定表。 关联到现有历史记录表时,可以选择执行数据一致性检查。 数据一致性检查可确保现有记录不重叠。 系统默认运行数据一致性检查。 对使用 SYSTEM_VERSIONING = ON 子句定义的表使用 PERIOD FOR SYSTEM_TIME 参数,使现有表成为时态表。 有关详细信息,请参阅 临时表

HISTORY_RETENTION_PERIOD = { INFINITE | number { DAY |DAYS |WEEK |WEEKS |MONTH |MONTHS |YEAR |YEARS } }

适用于:SQL Server 2017 (14.x) 和 Azure SQL 数据库。

指定时态表中历史数据的有限保留期或无限保留期。 如果省略,则假定为无限期保留。

DATA_DELETION

适用于:仅限 Azure SQL Edge

允许基于保留策略清除数据库内各表中的旧数据或过期数据。 有关详细信息,请参阅启用和禁用数据保留。 若要启用数据保留,必须指定以下参数。

  • FILTER_COLUMN = { column_name }

    指定用于确定表中的行是否过时的列。 筛选器列支持以下数据类型。

    • date
    • datetime
    • datetime2
    • smalldatetime
    • datetimeoffset
  • RETENTION_PERIOD = { INFINITE | number { DAY |DAYS |WEEK |WEEKS |MONTH |MONTHS |YEAR |YEARS } }

    指定表的保留期策略。 保留期指定为正整数值和日期部分单位的组合。

SET ( LOCK_ESCALATION = { AUTO |TABLE |DISABLE }

适用于:SQL Server 和 Azure SQL 数据库。

指定允许的对表的锁进行升级的方法。

  • AUTO

    借助此选项,SQL Server 数据库引擎 可选择适合于表架构的锁升级粒度。

    • 如果表已分区,则允许将锁提升到堆或 B 树(HoBT)粒度。 换句话说,允许升级到分区级别。 将锁升级到 HoBT 级别后,该锁以后不会升级到 TABLE 粒度。

    • 如果未对表进行分区,则会将锁升级为 TABLE 粒度。

  • TABLE

    无论表是否已分区,锁都升级到表级粒度。 默认值为 TABLE

  • DISABLE

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

REBUILD

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

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

PARTITION = ALL

适用于:SQL Server 和 Azure SQL 数据库。

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

REBUILD WITH ( <rebuild_option> )

为具有聚集索引的表应用所有选项。 如果表没有聚集索引,堆结构只受部分选项影响。

如果未使用作指定 REBUILD 特定的压缩设置,则使用分区的当前压缩设置。 若要返回当前设置,请在 data_compression 目录视图中查询 sys.partitions 列。

有关重新生成选项的完整说明,请参阅 ALTER TABLE index_option

DATA_COMPRESSION

适用于:SQL Server 和 Azure SQL 数据库。

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

  • NONE

    不压缩表或指定的分区。 此选项不适用于列存储表。

  • 使用行压缩对表或指定的分区进行压缩。 此选项不适用于列存储表。

  • 表或指定的分区使用页面压缩进行压缩。 此选项不适用于列存储表。

  • COLUMNSTORE

    适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

    仅适用于列存储表。 COLUMNSTORE 指定使用选项解压缩已 COLUMNSTORE_ARCHIVE 压缩的分区。 还原数据时,继续通过用于所有列存储表的列存储压缩来压缩数据。

  • COLUMNSTORE_ARCHIVE

    适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

    仅适用于列存储表,这是使用聚集列存储索引存储的表。 COLUMNSTORE_ARCHIVE 进一步将指定的分区压缩为较小的大小。 此选项可用于存档,或其他要求更少存储但能花更多时间用于存储和检索的情形。

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

    ALTER TABLE REBUILD PARTITION WITH DATA COMPRESSION = ROWPAGE 不允许在 Microsoft Fabric 预览版中的 SQL 数据库上使用。

XML_COMPRESSION

适用于:SQL Server 2022 (16.x) 及更高版本、Azure SQL 数据库和 Azure SQL 托管实例

为表中的任意 xml 数据类型列指定 XML 压缩选项。 选项如下:

  • ON

    压缩使用 xml 数据类型的列。

  • OFF

    未压缩使用 xml 数据类型的列。

OONLINE = { ON | OFF } <同样适用于 single_partition_rebuild_option>

指定基础表和相关索引的单个分区能否在索引操作执行期间用于查询和数据修改。 默认值为 OFF。 可以作为作ONLINE运行REBUILD

  • ON

    长期表锁在索引操作执行期间不保留。 在索引重新生成开始时,表需要 S 锁;在联机索引重新生成结束时,表需要 Sch-M 锁。 尽管两个锁都是短元数据锁,但 Sch-M 锁必须等待所有正在阻塞的事务都完成。 在等待期间,Sch-M 锁在访问同一表时阻止在此锁后等待的所有其他事务。

    Note

    联机索引重新生成可以设置本节稍后介绍的 low_priority_lock_wait 选项。

  • OFF

    在索引操作期间应用表锁。 这样可以防止所有用户在操作期间访问基础表。

column_set_name XML COLUMN_SET FOR ALL_SPARSE_COLUMNS

适用于:SQL Server 和 Azure SQL 数据库。

列集的名称。 列集是一种非类型化的 XML 表示形式,它将表的所有稀疏列合并为一种结构化的输出。 无法将列集添加到包含稀疏列的表。 有关列集的详细信息,请参阅 “使用列集”。

{ ENABLE |DISABLE } FILETABLE_NAMESPACE

适用于:SQL Server。

启用或禁用针对 FileTable 的系统定义约束。 仅可与 FileTable 一起使用。

SET (FILETABLE_DIRECTORY = directory_name

适用于:SQL Server。 Azure SQL 数据库不支持 FileTable。

指定与 Windows 兼容的 FileTable 目录名称。 此名称应在数据库的所有 FileTable 目录名称中唯一。 无论 SQL 排序规则设置如何,唯一性比较都不区分大小写。 仅可与 FileTable 一起使用。

REMOTE_DATA_ARCHIVE

适用于:SQL Server 2017 (14.x) 及更高版本。

为表启用或禁用 Stretch Database。 有关详细信息,请参阅 Stretch Database

Important

SQL Server 2022 (16.x) 和 Azure SQL 数据库中已弃用 Stretch Database。 在数据库引擎的未来版本中将删除此功能。 请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。

为表启用 Stretch Database

通过指定 ON 为表启用 Stretch 时,必须同时指定 MIGRATION_STATE = OUTBOUND 立即开始迁移数据或指定 MIGRATION_STATE = PAUSED 推迟迁移数据。 默认值是 MIGRATION_STATE = OUTBOUND。 若要详细了解如何为表启用 Stretch,请参阅为表启用 Stretch Database

Prerequisites. 为表启用 Stretch 之前,必须在服务器和数据库上启用 Stretch。 有关详细信息,请参阅为数据库启用 Stretch Database

Permissions. 为数据库或表启用 Stretch 需要 db_owner 权限。 为表启用 Stretch 还需要 ALTER 对表具有权限。

禁用表的 Stretch Database

为表禁用 Stretch 后,已迁移到 Azure 的远程数据的处理方式有两种。 有关详细信息,请参阅禁用 Stretch Database 并恢复远程数据

  • 要针对某个表禁用 Stretch 并将该表的远程数据从 Azure 复制回 SQL Server,请运行以下命令。 此命令不能取消。

    ALTER TABLE <table_name>
       SET ( REMOTE_DATA_ARCHIVE ( MIGRATION_STATE = INBOUND ) ) ;
    

此操作会产生数据传输费用,并且不可取消。 有关详细信息,请参阅数据传输定价详细信息

将所有远程数据从 Azure 复制回到 SQL Server 之后,将为表禁用延伸。

  • 若要为某个表禁用延伸并放弃远程数据,请运行以下命令。

    ALTER TABLE <table_name>
       SET ( REMOTE_DATA_ARCHIVE = OFF_WITHOUT_DATA_RECOVERY ( MIGRATION_STATE = PAUSED ) ) ;
    

为表禁用 Stretch Database 之后,数据迁移会停止,查询结果不再包括来自远程表的结果。

禁用 Stretch 不会删除远程表。 若要删除远程表,请使用 Azure 门户删除它。

[ FILTER_PREDICATE = { null | 谓词 }]

适用于:SQL Server 2017 (14.x) 及更高版本。

根据需要,指定一个筛选器谓词,从包含历史数据和最新数据的表中选择要迁移的行。 该谓词必须调用确定性的内联表值函数。 有关详细信息,请参阅为表启用 Stretch Database使用筛选器函数选择要迁移的行

Important

如果提供的筛选器谓词性能不佳,则数据迁移性能也不佳。 Stretch Database 使用 CROSS APPLY 运算符将筛选器谓词应用于表。

如果未指定筛选器谓词,则将迁移整个表。

指定筛选器谓词时,还必须指定 MIGRATION_STATE

MIGRATION_STATE = { OUTBOUND |INBOUND |PAUSED }

适用于:SQL Server 2017 (14.x) 及更高版本。

WAIT_AT_LOW_PRIORITY

适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

联机索引重新生成必须等待对此表执行的阻塞操作。 WAIT_AT_LOW_PRIORITY 指示联机索引重新生成作等待低优先级锁,从而允许在联机索引生成作等待时执行其他作。 省略该 WAIT AT LOW PRIORITY 选项与 WAIT_AT_LOW_PRIORITY ( MAX_DURATION = 0 minutes, ABORT_AFTER_WAIT = NONE).

MAX_DURATION = 时间 [ 分钟 ]

适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

等待时间(以分钟为单位指定的整数值),运行 DDL 命令时, SWITCH 或联机索引重新生成锁定会以低优先级等待。 如果作在一段时间内被 MAX_DURATION 阻止,则 ABORT_AFTER_WAIT 其中一个作将运行。 MAX_DURATION 时间始终以分钟为单位,你可以省略单词 MINUTES

ABORT_AFTER_WAIT = { NONE |SELF |BLOCKERS }

适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

  • NONE

    继续以普通(常规)优先级等待锁。

  • SELF

    SWITCH退出当前运行的或联机索引重新生成 DDL作,而无需执行任何作。

  • BLOCKERS

    终止当前阻止 SWITCH 或联机索引重新生成 DDL作的所有用户事务,以便该作可以继续。

    ALTER ANY CONNECTION需要权限。

IF EXISTS

适用于:SQL Server 2016(13.x)及更高版本以及 Azure SQL 数据库。

有条件地删除列或约束(仅当存在时)。

可恢复 = { ON |OFF}

适用于:SQL Server 2022(16.x)及更高版本。

指定 ALTER TABLE ADD CONSTRAINT 操作是否可恢复。 添加表约束操作在 ON 时是可恢复的。 添加表约束操作在 OFF 时是可恢复的。 默认值为 OFFRESUMABLE 选项可用作 ALTER TABLE table_constraintALTER TABLE index_option 的一部分。

MAX_DURATION与 (requiresONLINE = ON) 一起使用RESUMABLE = ON时,指示在暂停之前执行可恢复联机添加约束作的时间(以分钟为单位指定的整数值)。 如果未指定,则操作会一直持续到完成。

有关启用和使用可 ALTER TABLE ADD CONSTRAINT 恢复作的详细信息,请参阅 “可恢复添加表约束”。

Remarks

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

如果过程缓存中有任何引用表的执行计划, ALTER TABLE 请在下次执行时将其标记为重新编译。

在 Microsoft Fabric 预览版中的 SQL 数据库中,可以创建某些表功能,但不会 镜像到 Fabric OneLake 中。 有关详细信息,请参阅 Fabric SQL 数据库镜像的限制(预览版)。

更改列的大小

可以指定列数据类型的新大小,从而更改列的长度、精度或确定位数。 使用子 ALTER COLUMN 句。 如果列中有数据,新大小不得小于数据的大小上限。 此外,不能在索引中定义列,除非列是 varcharnvarcharvarbinary 数据类型,并且索引不是约束的结果 PRIMARY KEY 。 请参阅标题为更改列定义的小节中的示例。

锁和 ALTER TABLE

在实现中 ALTER TABLE 立即指定的更改。 如果更改需要修改表中的行,请 ALTER TABLE 更新这些行。 ALTER TABLE 获取表上的架构修改 (Sch-M) 锁,以确保在更改期间,即使没有其他连接引用表的元数据,但最终需要短 Sch-M 锁的联机索引作除外。 在 ALTER TABLE...SWITCH 操作中,源表和目标表都需要锁。 对表进行的更改将记录于日志中,并且可以完整恢复。 影响大型表中所有行的更改(例如删除列或在某些版本的 SQL Server 上添加 NOT NULL 具有默认值的列)可能需要很长时间才能完成并生成许多日志记录。 运行这些 ALTER TABLE 语句,其处理方式与任何 INSERT语句 UPDATE相同,或 DELETE 影响许多行的语句。

适用于 Microsoft Fabric 中的仓库。

ALTER TABLE 不能是显式事务的一部分。

分区交换机的扩展事件 (XEvents)

以下 XEvent 与 ALTER TABLE ... SWITCH PARTITION联机索引重新生成相关。

  • lock_request_priority_state
  • process_killed_by_abort_blockers
  • ddl_with_wait_at_low_priority

以联机操作的形式添加 NOT NULL 列

在 SQL Server 2012 (11.x) Enterprise Edition 及更高版本中,当默认值为运行时常量时,添加NOT NULL具有默认值的列是联机作。 也就是说,无论表中有多少行,此操作都几乎可以瞬间完成。这是因为,表中的现有行在操作执行期间不更新。 相反,默认值仅存储在表的元数据中,且能根据需要通过访问这些行的查询来查找默认值。 这种行为是自动的。 除了语法之外,不需要任何其他语法来实现联机作 ADD COLUMN 。 运行时常量是表达式,它可以在运行时为表中的每一行都生成相同的值,无论确定性如何。 例如,常量表达式 "My temporary data"或系统函数 GETUTCDATETIME() 是运行时常量。 相比之下,函数 NEWID()NEWSEQUENTIALID() 就不是运行时常量,因为这些函数为表中的每一行都生成唯一值。 NOT NULL添加默认值不是运行时常量的列始终脱机运行,并在作期间获取排他锁(Sch-M) 锁。

尽管现有行引用元数据中存储的值,但对于已插入但不为列指定其他值的任何新行,默认值存储在行中。 更新行时,元数据中存储的默认值将移动到现有行(即使语句中 UPDATE 未指定实际列),或者重新生成表或聚集索引。

无法在联机作中添加 varchar(max)nvarchar(max)varbinary(max)xmltextntextimagehierarchyidgeometrygeography 或 CLR 用户定义类型的列。 如果列会导致最大可能行大小超过 8,060 字节限制,无法联机添加列。 在这种情况下将在脱机操作中添加列。

并行计划执行

在 SQL Server 2012 (11.x) Enterprise Edition 及更高版本中,用于运行单个 ALTER TABLE ADD (基于索引) CONSTRAINTDROP (聚集索引) CONSTRAINT 语句的处理器数取决于 最大并行度 配置选项和当前工作负荷。 如果数据库引擎检测到系统正忙,则在语句执行开始之前将自动降低操作并行度。 可以通过指定 MAXDOP 选项来手动配置用于运行语句的处理器数。 有关详细信息,请参阅 服务器配置:最大并行度

分区表

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

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

应用于 ALTER TABLE 具有架构绑定视图的表上的语句的限制与修改具有简单索引的表时当前应用的限制相同。 允许添加列。 不过,禁止删除或更改参与任何架构绑定视图的列。 ALTER TABLE如果语句需要更改在架构绑定视图中使用的列,ALTER TABLE则失败,数据库引擎将引发错误消息。 有关架构绑定和索引视图的详细信息,请参阅 CREATE VIEW

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

索引和 ALTER TABLE

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

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

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

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

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

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

删除聚集索引时,请指定 ONLINE = ON 该选项,以便事务 DROP INDEX 不会阻止对基础数据和关联的非聚集索引的查询和修改。

ONLINE = ON 具有以下限制:

  • ONLINE = ON 对于也禁用的聚集索引无效。 必须使用 删除 ONLINE = OFF禁用的索引。
  • 一次只能删除一个索引。
  • ONLINE = ON 对于本地临时表的索引视图、非聚集索引或索引无效。
  • ONLINE = ON 对列存储索引无效。

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

Note

下面 <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 ... 语法重新生成所有分区。

删除 ntext 列

使用已弃用 的 ntext 数据类型删除列时,删除的数据的清理将作为所有行的序列化作进行。 清理可能需要大量时间才能完成。 在包含大量行的表中删除 ntext 列时,请先将 ntext 列更新为 NULL 值,然后删除该列。 可以使用并行操作运行此选项,并加快速度。

联机索引重新生成

若要为联机索引重新生成操作运行 DDL 语句,必须完成对特定表运行的所有正在阻塞的事务。 在联机索引重新生成启动时,它会阻止所有准备开始对此表运行的新事务。 尽管联机索引重新生成锁的持续时间较短,但等待给定表的所有待处理事务完成,以及阻止新事务启动可能会对吞吐量产生很大影响。 这可能会导致工作负载变慢或超时,并严重限制对基础表的访问。 此选项 WAIT_AT_LOW_PRIORITY 允许 DBA 管理联机索引重新生成所需的 S 锁和 Sch-M 锁。 在所有三种情况下: NONESELF如果在 BLOCKERS等待期间((MAX_DURATION = n [minutes]))没有阻塞活动,则立即运行联机索引重新生成,且 DDL 语句已完成。

兼容性支持

ALTER TABLE 语句仅支持由两部分构成的表schema.object名。 在 SQL Server 中,使用以下格式指定表名称时,在编译时会出现错误 117。

  • server.database.schema.table
  • .database.schema.table
  • ..schema.table

在早期版本中指定格式 server.database.schema.table 会返回错误 4902。 指定格式 .database.schema.table..schema.table 则会成功。

若要解决此问题,请不要使用包含四部分的前缀。

Permissions

ALTER需要对表具有权限。

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

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

添加或更改更新表行的列需要 UPDATE 对表具有权限。 例如,当表不为空时,添加 NOT NULL 具有默认值的列或添加标识列。

Examples

本文中的代码示例使用 AdventureWorks2022AdventureWorksDW2022 示例数据库,可以从 Microsoft SQL Server 示例和社区项目 主页下载该数据库。

Category 作为特征的语法元素
添加列和约束 ADD; PRIMARY KEY 包含索引选项、稀疏列和列集
删除列和约束 DROP
更改列定义 更改数据类型;更改列大小;整理
更改表定义 DATA_COMPRESSION; SWITCH PARTITION; ; LOCK ESCALATION更改跟踪
禁用和启用约束和触发器 CHECK;NO CHECK; ; ENABLE TRIGGERDISABLE TRIGGER
联机作 ONLINE
系统版本控制 SYSTEM_VERSIONING

添加列和约束

本节中的示例说明将列和约束添加到表中。

A. 添加新列

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

CREATE TABLE dbo.doc_exa (column_a INT);
GO

ALTER TABLE dbo.doc_exa
    ADD column_b VARCHAR (20) NULL;
GO

B. 添加包含约束的列

以下示例将添加一个包含 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

EXECUTE sp_help doc_exc;
GO

DROP TABLE dbo.doc_exc;
GO

C. 在现有列中添加一个未经验证的 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

EXECUTE sp_help doc_exd;
GO

DROP TABLE dbo.doc_exd;
GO

D. 在现有列中添加一个 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

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

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

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

ALTER TABLE dbo.doc_exe

    -- Add a PRIMARY KEY identity column.
    ADD 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 FOREIGN KEY 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

EXECUTE sp_help doc_exe;
GO

DROP TABLE dbo.doc_exe;
GO

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

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

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
        CONSTRAINT AddDateDflt DEFAULT GETDATE() WITH VALUES NULL;
GO

DROP TABLE dbo.doc_exf;
GO

G. 使用索引或数据压缩选项创建 PRIMARY KEY 约束

以下示例创建PRIMARY KEY约束并设置选项FILLFACTORONLINEPAD_INDEXPK_TransactionHistoryArchive_TransactionID 生成的聚集索引与约束同名。

适用于:SQL Server 和 Azure SQL 数据库。

USE AdventureWorks2022;
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

此类似示例在应用群集主键时应用页面压缩。

USE AdventureWorks2022;
GO

ALTER TABLE Production.TransactionHistoryArchive WITH NOCHECK
    ADD CONSTRAINT PK_TransactionHistoryArchive_TransactionID
        PRIMARY KEY CLUSTERED (TransactionID) WITH (DATA_COMPRESSION = PAGE);
GO

H. 添加稀疏列

下面的示例演示如何在表 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

I. 添加列集

下面的示例演示如何向表 T2 中添加一列。 无法将列集添加到已包含稀疏列的表。 创建表 T2 的代码如下所示。

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

下面的三个语句添加名为 CS 的列集,然后将列 C2C3 修改为 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

J. 添加加密列

以下语句将添加名为 PromotionCode 的加密列。

ALTER TABLE Customers
    ADD PromotionCode NVARCHAR (100)
        ENCRYPTED WITH (
            COLUMN_ENCRYPTION_KEY = MyCEK,
            ENCRYPTION_TYPE = RANDOMIZED,
            ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
        );

K. 使用可恢复操作添加主键

用于添加聚集在 (a) 列上的主键的可恢复 ALTER TABLE 操作,MAX_DURATION 为 240 分钟。

ALTER TABLE table1
ADD CONSTRAINT PK_Constrain PRIMARY KEY CLUSTERED (a)
WITH (ONLINE = ON, MAXDOP = 2, RESUMABLE = ON, MAX_DURATION = 240);

删除列和约束

本节中的示例说明如何删除列和约束。

A. 删除一列或多列

第一个示例将修改一个表以删除列。 第二个示例删除多列。

CREATE TABLE dbo.doc_exb
(
    column_a INT,
    column_b VARCHAR (20) NULL,
    column_c DATETIME,
    column_d INT
);
GO

-- Remove a single column.
ALTER TABLE dbo.doc_exb DROP COLUMN column_b;
GO

-- Remove multiple columns.
ALTER TABLE dbo.doc_exb DROP COLUMN column_c, column_d;

B. 删除约束和列

第一个示例将从表中删除 UNIQUE 约束。 第二个示例将删除两个约束和一列。

CREATE TABLE dbo.doc_exc
(
    column_a INT NOT NULL
        CONSTRAINT my_constraint UNIQUE
);
GO

-- Example 1. Remove a single constraint.
ALTER TABLE dbo.doc_exc DROP my_constraint;
GO

DROP TABLE dbo.doc_exc;
GO

CREATE TABLE dbo.doc_exc
(
    column_a INT NOT NULL
        CONSTRAINT my_constraint UNIQUE,
    column_b INT NOT NULL
        CONSTRAINT my_pk_constraint PRIMARY KEY
);
GO

-- Example 2. Remove two constraints and one column
-- The keyword CONSTRAINT is optional. The keyword COLUMN is required.
ALTER TABLE dbo.doc_exc
    DROP CONSTRAINT my_constraint, my_pk_constraint, COLUMN column_b;
GO

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

以下示例删除PRIMARY KEYONLINE选项设置为 ON..

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

D. 添加和删除 FOREIGN KEY 约束

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

CREATE TABLE Person.ContactBackup (ContactID INT);
GO

ALTER TABLE Person.ContactBackup
    ADD CONSTRAINT FK_ContactBackup_Contact
        FOREIGN KEY (ContactID) REFERENCES Person.Person (BusinessEntityID);
GO

ALTER TABLE Person.ContactBackup
    DROP CONSTRAINT FK_ContactBackup_Contact;
GO

DROP TABLE Person.ContactBackup;

更改列定义

A. 更改列的数据类型

下面的示例将表中列的数据类型由 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

B. 更改列的大小

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

-- 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');

C. 更改列排序规则

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

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

D. 加密列

以下示例演示如何使用具有安全 enclave 的 Always Encrypted 加密列。

首先,将创建没有任何加密列的表。

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

接着,使用列加密密钥(名为 CEK1)和随机加密来加密列“C2”。 若要成功执行下面的语句,必须满足以下条件:

  • 列加密密钥必须已启用 enclave。 这意味着,必须使用允许 enclave 计算的列主密钥(CMK)对其进行加密。
  • 目标 SQL Server 实例必须支持具有安全 enclave 的 Always Encrypted。
  • 必须通过为具有安全 enclave 的 Always Encrypted 设置的连接且使用受支持的客户端驱动程序发出该语句。
  • 调用应用程序必须有权访问 CMK,保护 CEK1
ALTER TABLE T3 ALTER COLUMN C2 VARCHAR (50)  ENCRYPTED WITH (
     COLUMN_ENCRYPTION_KEY = [CEK1],
     ENCRYPTION_TYPE = RANDOMIZED,
     ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
    ) NULL;
GO

更改表定义

本节中的示例说明如何更改表定义。

A. 修改表以更改压缩

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

ALTER TABLE T1 REBUILD
    WITH (DATA_COMPRESSION = PAGE);

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

适用于:SQL Server。

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

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

适用于:SQL Server。

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

有关其他数据压缩示例,请参阅 数据压缩

B. 修改列存储表以便更改存档压缩

下面的示例通过应用附加的压缩算法,进一步压缩列存储表分区。 此压缩会缩小表大小,但也延长了存储和检索所需的时间。 这可用于存档,或者用于要求更少空间并且可以付出更多时间来进行存储和检索的其他情形。

适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

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

以下示例解压缩使用 COLUMNSTORE_ARCHIVE 选项压缩的列存储表分区。 还原数据时,继续通过用于所有列存储表的列存储压缩来压缩数据。

适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

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

C. 在表之间切换分区

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

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

以下示例在已分区表的分区级别启用锁升级。 如果未对表进行分区,则会在 TABLE 级别设置锁升级。

适用于:SQL Server 和 Azure SQL 数据库。

ALTER TABLE dbo.T1 SET (LOCK_ESCALATION = AUTO);
GO

E. 配置表上的更改跟踪

下面的示例对 Person.Person 表启用了更改跟踪。

适用于:SQL Server 和 Azure SQL 数据库。

USE AdventureWorks2022;

ALTER TABLE Person.Person ENABLE CHANGE_TRACKING;

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

适用于:SQL Server。

USE AdventureWorks2022;
GO

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

下面的示例对 Person.Person 表禁用更改跟踪。

适用于:SQL Server 和 Azure SQL 数据库。

USE AdventureWorks2022;
GO

ALTER TABLE Person.Person DISABLE CHANGE_TRACKING;

禁用和启用约束和触发器

A. 禁用和重新启用约束

以下示例中禁用了用于限制数据中所接受薪水的约束。 NOCHECK CONSTRAINTALTER 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 fails.
ALTER TABLE dbo.cnst_example CHECK CONSTRAINT salary_cap;
INSERT INTO dbo.cnst_example VALUES (4, 'Eric James', 110000);

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

下面的示例将使用 DISABLE TRIGGERALTER TABLE 选项来禁用触发器,以允许执行通常会违反此触发器的插入操作。 然后,使用 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;
           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

联机作

A. 使用低优先级等待选项的联机索引重新生成

下面的示例展示了如何执行指定低优先级等待选项的联机索引重新生成。

适用于:SQL Server 2014(12.x)及更高版本以及 Azure SQL 数据库。

ALTER TABLE T1 REBUILD WITH (
    PAD_INDEX = ON,
    ONLINE = ON (
        WAIT_AT_LOW_PRIORITY (MAX_DURATION = 4 MINUTES, ABORT_AFTER_WAIT = BLOCKERS)
    )
);

B. 联机更改列

以下示例演示如何使用 ONLINE 选项运行更改列作。

适用于:SQL Server 2016(13.x)及更高版本以及 Azure SQL 数据库。

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) WITH (ONLINE = ON);
GO

EXECUTE sp_help doc_exy;
DROP TABLE dbo.doc_exy;
GO

系统版本控制

以下四个示例可帮助你熟悉使用系统版本控制的语法。 有关其他帮助,请参阅 系统版本控制的临时表入门

适用于:SQL Server 2016(13.x)及更高版本以及 Azure SQL 数据库。

A. 向现有表添加系统版本控制

以下示例演示如何向现有表添加系统版本控制和创建后续的历史记录表。 此示例假定存在已定义主键的现有表 InsurancePolicy。 此示例使用开始时间和结束时间的默认值填充新创建的时间段列,以实现系统版本控制,因为这些值不得为 NULL。 此示例使用 HIDDEN 子句来确保对与当前表交互的现有应用程序没有任何影响。 它还使用 HISTORY_RETENTION_PERIOD 仅适用于 SQL 数据库。

--Alter non-temporal table to define periods for system versioning
ALTER TABLE InsurancePolicy
    ADD ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN
            DEFAULT SYSUTCDATETIME() NOT NULL,
        ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN
            DEFAULT CONVERT (DATETIME2, '9999-12-31 23:59:59.99999999') NOT NULL,
        PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo);

--Enable system versioning with 1 year retention for historical data
ALTER TABLE InsurancePolicy SET (
    SYSTEM_VERSIONING = ON (
        HISTORY_RETENTION_PERIOD=1 YEAR
    )
);

B. 迁移现有解决方案以使用系统版本控制

以下示例演示如何从使用触发器模拟临时支持的解决方案迁移到系统版本控制。 该示例假定有一个现有解决方案使用表和ProjectTaskHistory表作为其现有解决方案ProjectTask,该解决方案使用Changed Date其句点和Revised Date列,这些句点列不使用 datetime2 数据类型,并且ProjectTask表定义了主键。

-- Drop existing trigger
DROP TRIGGER ProjectTask_HistoryTrigger;

-- Adjust the schema for current and history table
-- Change data types for existing period columns
ALTER TABLE ProjectTask ALTER COLUMN [Changed Date] DATETIME2 NOT NULL;
ALTER TABLE ProjectTask ALTER COLUMN [Revised Date] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory ALTER COLUMN [Changed Date] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory ALTER COLUMN [Revised Date] DATETIME2 NOT NULL;

-- Add SYSTEM_TIME period and set system versioning with linking two existing tables
-- (a certain set of data checks happen in the background)
ALTER TABLE ProjectTask
    ADD PERIOD FOR SYSTEM_TIME ([Changed Date], [Revised Date]);

ALTER TABLE ProjectTask SET (
    SYSTEM_VERSIONING = ON (
        HISTORY_TABLE=dbo.ProjectTaskHistory, DATA_CONSISTENCY_CHECK=ON
    )
);

C. 禁用和重新启用系统版本控制以更改表架构

此示例演示如何对 Department 表禁用系统版本控制、添加列以及重新启用系统版本控制。 必须先禁用系统版本控制,然后才能修改表架构。 在事务中执行这些步骤可阻止在更新表架构时更新两个表,这样可让 DBA 在重新启用系统版本控制时跳过数据一致性检查,并获得性能优势。 创建统计信息、切换分区或压缩一个或两个表等任务不需要禁用系统版本控制。

BEGIN TRAN
/* Takes schema lock on both tables */
ALTER TABLE Department
    SET (SYSTEM_VERSIONING = OFF) ;
/* expand table schema for temporal table */
ALTER TABLE Department
     ADD Col5 int NOT NULL DEFAULT 0 ;
/* Expand table schema for history table */
ALTER TABLE DepartmentHistory
    ADD Col5 int NOT NULL DEFAULT 0 ;
/* Re-establish versioning again*/
ALTER TABLE Department
    SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=dbo.DepartmentHistory,
                                 DATA_CONSISTENCY_CHECK = OFF)) ;
COMMIT

D. 删除系统版本控制

此示例演示如何完全删除 Department 表中的系统版本控制并删除 DepartmentHistory 表。 也可以根据需要删除系统用于记录系统版本控制信息的时间段列。 当系统版本控制处于启用状态时,无法删除 DepartmentDepartmentHistory 表。

ALTER TABLE Department
    SET (SYSTEM_VERSIONING = OFF);

ALTER TABLE Department
    DROP PERIOD FOR SYSTEM_TIME;

DROP TABLE DepartmentHistory;

示例:Azure Synapse Analytics 和 Analytics Platform System (PDW)

以下 A 到 C 示例均使用 AdventureWorksPDW2022FactResellerSales 数据库中的 表。

A. 确定是否已将表分区

如果表 FactResellerSales 已分区,以下查询将返回一个或多个行。 如果表未分区,则不返回任何行。

SELECT *
FROM sys.partitions AS p
     INNER JOIN sys.tables AS t
         ON p.object_id = t.object_id
WHERE p.partition_id IS NOT NULL
      AND t.name = 'FactResellerSales';

B. 为已分区表确定边界值

以下查询对于 FactResellerSales 表中的每个分区返回边界值。

SELECT t.name AS TableName,
       i.name AS IndexName,
       p.partition_number,
       p.partition_id,
       i.data_space_id,
       f.function_id,
       f.type_desc,
       r.boundary_id,
       r.value AS BoundaryValue
FROM sys.tables AS t
     INNER JOIN sys.indexes AS i
         ON t.object_id = i.object_id
     INNER JOIN sys.partitions AS p
         ON i.object_id = p.object_id
        AND i.index_id = p.index_id
     INNER JOIN sys.partition_schemes AS s
         ON i.data_space_id = s.data_space_id
     INNER JOIN sys.partition_functions AS f
         ON s.function_id = f.function_id
     LEFT OUTER JOIN sys.partition_range_values AS r
         ON f.function_id = r.function_id
        AND r.boundary_id = p.partition_number
WHERE t.name = 'FactResellerSales'
      AND i.type <= 1
ORDER BY p.partition_number;

C. 为已分区表的确定分区列

以下查询返回表的分区列 FactResellerSales 的名称。

SELECT t.object_id AS Object_ID,
       t.name AS TableName,
       ic.column_id AS PartitioningColumnID,
       c.name AS PartitioningColumnName
FROM sys.tables AS t
     INNER JOIN sys.indexes AS i
         ON t.object_id = i.object_id
     INNER JOIN sys.columns AS c
         ON t.object_id = c.object_id
     INNER JOIN sys.partition_schemes AS ps
         ON ps.data_space_id = i.data_space_id
     INNER JOIN sys.index_columns AS ic
         ON ic.object_id = i.object_id
        AND ic.index_id = i.index_id
        AND ic.partition_ordinal > 0
WHERE t.name = 'FactResellerSales'
      AND i.type <= 1
      AND c.column_id = ic.column_id;

D. 合并两个分区

以下示例合并表上的两个分区。

Customer 表具有以下定义:

CREATE TABLE Customer
(
    id INT NOT NULL,
    lastName VARCHAR (20),
    orderCount INT,
    orderDate DATE
)
WITH (
    DISTRIBUTION = HASH(id),
    PARTITION(orderCount RANGE LEFT
        FOR VALUES (1, 5, 10, 25, 50, 100)
    )
);

以下命令合并 10 和 25 分区边界。

ALTER TABLE Customer MERGE RANGE (10);

表的新 DDL 是:

CREATE TABLE Customer
(
    id INT NOT NULL,
    lastName VARCHAR (20),
    orderCount INT,
    orderDate DATE
)
WITH (
    DISTRIBUTION = HASH(id),
    PARTITION(orderCount RANGE LEFT
        FOR VALUES (1, 5, 25, 50, 100)
    )
);

E. 拆分分区

以下示例拆分表上的分区。

Customer 表具有以下 DDL:

DROP TABLE Customer;

CREATE TABLE Customer
(
    id INT NOT NULL,
    lastName VARCHAR (20),
    orderCount INT,
    orderDate DATE
)
WITH (
    DISTRIBUTION = HASH(id),
    PARTITION(orderCount RANGE LEFT
        FOR VALUES (1, 5, 10, 25, 50, 100)
    )
);

以下命令创建值为 75(50 到 100 之间)的新分区边界。

ALTER TABLE Customer SPLIT RANGE (75);

表的新 DDL 是:

CREATE TABLE Customer (
   id INT NOT NULL,
   lastName VARCHAR(20),
   orderCount INT,
   orderDate DATE)
   WITH DISTRIBUTION = HASH(id),
   PARTITION ( orderCount (RANGE LEFT
      FOR VALUES (1, 5, 10, 25, 50, 75, 100))) ;

F. 使用 SWITCH 将分区移至历史记录表

以下示例将 Orders 表的分区中的数据移动到 OrdersHistory 表的分区中。

Orders 表具有以下 DDL:

CREATE TABLE Orders
(
    id INT,
    city VARCHAR (25),
    lastUpdateDate DATE,
    orderDate DATE
)
WITH (
    DISTRIBUTION = HASH(id),
    PARTITION(orderDate RANGE RIGHT
        FOR VALUES ('2004-01-01', '2005-01-01', '2006-01-01', '2007-01-01')
    )
);

在此示例中,Orders 表具有以下分区。 每个分区中均包含数据。

Partition 是否有数据? 边界范围
1 Yes OrderDate < '2004-01-01'
2 Yes '2004-01-01' <= OrderDate < '2005-01-01'
3 Yes '2005-01-01' <= OrderDate< '2006-01-01'
4 Yes '2006-01-01'<= OrderDate < '2007-01-01'
5 Yes '2007-01-01' <= OrderDate
  • 分区 1 (包含数据): OrderDate < '2004-01-01'
  • 分区 2 (包含数据): '2004-01-01' <= OrderDate < '2005-01-01'
  • 分区 3 (包含数据): '2005-01-01' <= OrderDate< '2006-01-01'
  • 分区 4 (包含数据): '2006-01-01'<= OrderDate < '2007-01-01'
  • 分区 5 (包含数据): '2007-01-01' <= OrderDate

OrdersHistory 表具有以下 DDL,其列和列名称与 Orders 表一致。 两者在 id 列上都是哈希分布式。

CREATE TABLE OrdersHistory
(
    id INT,
    city VARCHAR (25),
    lastUpdateDate DATE,
    orderDate DATE
)
WITH (
    DISTRIBUTION = HASH(id),
    PARTITION(orderDate RANGE RIGHT
        FOR VALUES ('2004-01-01')
    )
);

虽然列和列名必须相同,但分区边界不必相同。 在此示例中,OrdersHistory 表具有以下两个分区,并且这两个分区都为空:

  • 分区 1 (无数据): OrderDate < '2004-01-01'
  • 分区 2 (空): '2004-01-01' <= OrderDate

对于上述两个表,以下命令将具有 OrderDate < '2004-01-01' 的所有行从 Orders 表移到 OrdersHistory 表。

ALTER TABLE Orders SWITCH PARTITION 1 TO OrdersHistory PARTITION 1;

因此,Orders 中的第一个分区为空,OrdersHistory 中的第一个分区中包含数据。 现在的表如下所示:

Orders

  • 分区 1 (空): OrderDate < '2004-01-01'
  • 分区 2 (包含数据): '2004-01-01' <= OrderDate < '2005-01-01'
  • 分区 3 (包含数据): '2005-01-01' <= OrderDate< '2006-01-01'
  • 分区 4 (包含数据): '2006-01-01'<= OrderDate < '2007-01-01'
  • 分区 5 (包含数据): '2007-01-01' <= OrderDate

OrdersHistory

  • 分区 1 (包含数据): OrderDate < '2004-01-01'
  • 分区 2 (空): '2004-01-01' <= OrderDate

若要清理 Orders 表,可以通过合并分区来删除空分区 12 如下所示:

ALTER TABLE Orders MERGE RANGE ('2004-01-01');

合并后,Orders 表具有以下分区:

Orders

  • 分区 1 (包含数据): OrderDate < '2005-01-01'
  • 分区 2 (包含数据): '2005-01-01' <= OrderDate< '2006-01-01'
  • 分区 3 (包含数据): '2006-01-01'<= OrderDate < '2007-01-01'
  • 分区 4 (包含数据): '2007-01-01' <= OrderDate

假设又过去了一年,你准备存档 2005 年的数据。 可以通过拆分空分区为 OrdersHistory 表中的 2005 年分配空的分区,如下所示:

ALTER TABLE OrdersHistory SPLIT RANGE ('2005-01-01');

拆分后,OrdersHistory 表具有以下分区:

OrdersHistory

  • 分区 1 (包含数据): OrderDate < '2004-01-01'
  • 分区 2 (空): '2004-01-01' < '2005-01-01'
  • 分区 3 (空): '2005-01-01' <= OrderDate