SQL Server ALTER TABLE ADD列概述

本文深入探讨了SQL Server中ALTER TABLE ADD Column语句的使用,用于向现有表添加列。文章强调了添加具有默认值的列以及在大型表中更新列的影响,说明了2012年以后版本的SQL Server如何优化这一过程,以减少对表的锁定和资源消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In this article, we will explore SQL Server ALTER TABLE ADD Column statements to add column(s) to an existing table. We will also understand the impact of adding a column with a default value and adding and updating the column with a value later on larger tables.

在本文中,我们将探索SQL Server ALTER TABLE ADD Column语句,以将列添加到现有表中。 我们还将理解在较大的表上添加具有默认值的列以及添加和更新具有值的列的影响。

As a database developer, you need to add columns to the existing tables too offen. You would think that adding a column to the SQL Server database table would not be a major deal. Sometimes you might be adding the column from the SQL Server Management Studio itself. Well, that would be fine for a small table or a table which does not have a large number of transactions. Let’s go ahead and see how we can add columns to an existing table and also understand the reasons and the best practices to add a column to a table that is large in size.

作为数据库开发人员,您还需要向现有表中添加列。 您可能会认为向SQL Server数据库表中添加列并不是一件大事。 有时您可能是从SQL Server Management Studio本身添加该列。 好吧,这对于较小的表或没有大量事务的表会很好。 让我们继续前进,看看如何将列添加到现有表中,并了解向大型表添加列的原因和最佳实践。

样品表 (Sample Table)

Let us create a sample table with sufficient data set from the following script.

让我们用以下脚本创建一个具有足够数据集的示例表。

IF EXISTS (SELECT 1 FROM Sys.tables where Name = 'SampleTable')
DROP TABLE SampleTable
 
CREATE TABLE dbo.SampleTable (
   ID BIGINT IDENTITY (1,1) NOT NULL PRIMARY KEY CLUSTERED,
   DateTime4 DATETIME DEFAULT GETDATE(),
   Column1 CHAR(1000) DEFAULT 'MMMMMMMMMMMMMMMMM',
   Column2 CHAR(2000) DEFAULT 'YYYYYYYYYYYYYYYYY'
)

The above script will create a sample table called SampleTable. Data fields are added so that the large size table will be created. Next, a large number of records were added by executing the following query multiple times.

上面的脚本将创建一个名为SampleTable的示例表。 添加了数据字段,以便创建大型表。 接下来,通过多次执行以下查询来添加大量记录。

SET NOCOUNT ON
INSERT INTO SampleTable
(DateTime4, Column1, Column2)
VALUES
(GETDATE(),'XXXX','YYYY')
GO 500000

After the above query is executed, 500,000 records are updated to the SampleTable. After executing the above query following is the table size and other parameters for the table.

执行以上查询后,将500,000条记录更新到SampleTable 。 执行上述查询后,下面是表的大小和该表的其他参数。

This can be retrieved by sp_spaceused ‘SampleTable’

可以通过sp_spaceused'SampleTable'进行检索

Table size and other parameters

The following is the database size for data and the log file.

以下是数据和日志文件的数据库大小。

Database file sizes, transaction log file.

Let’s quickly go over the syntax of adding one column to an existing table by using ALTER TABLE ADD statement as shown below.

让我们快速遍历使用ALTER TABLE ADD语句向现有表中添加一列的语法,如下所示。

ALTER TABLE tbl_name
ADD Col_name  data_type  col_constraint;

You can use the below statement to add column NewColumn1 to our table SampleTable.

您可以使用以下语句将NewColumn1列添加到我们的表SampleTable中。

ALTER TABLE SampleTable
ADD NewColumn1 varchar(200)

Also, you can add multiple columns to a table using the single SQL Server ALTER TABLE statement as below.

另外,您可以使用单个SQL Server ALTER TABLE语句将多个列添加到表中,如下所示。

ALTER TABLE SampleTable
ADD NewColumn2 varchar(20),
NewColumn3 varchar(50)

When adding a column to a large table, typically you want to add the column and fill the added column with a default value. For example, if you want to add a status column, next is to fill the column with a default value.

将列添加到大型表时,通常需要添加该列,并使用默认值填充添加的列。 例如,如果要添加状态列,则下一步是用默认值填充该列。

添加具有默认约束的列 (Adding a Column with a Default Constraints)

To achieve the above objective, the easiest way is to add a column with a default constraint. When the default column is added, the default value will be added to the table. The following script makes use of SQL Server ALTER TABLE ADD Column (Status in our case) statement to add a column named Status with default constraint.

为了实现上述目的,最简单的方法是添加具有默认约束的列。 添加默认列后,默认值将添加到表中。 以下脚本利用SQL Server ALTER TABLE ADD Column(在本例中为Status)语句添加具有默认约束的名为Status的列。

ALTER TABLE SampleTable 
ADD Status CHAR(5000) 
DEFAULT 'INC' WITH VALUES

When the column is added as above, the Status column will be added with the Value INC for all records.

当按上述方式添加列时,将为所有记录添加“状态”列和“值INC”。

From the profiler following statics are captured via SQL Profiler during the column addition with default values.

在添加默认值的列期间,通过SQL事件探查器从事件探查器捕获以下静态信息。

CPU

0

Reads

185

Writes

0

Duration Mille Seconds

65

中央处理器

0

185

0

持续时间毫秒

65

You can see that the column is added to the table even less than one second and operation is very minimal cost.

您可以看到该列添加到表中的时间甚至不到一秒钟,并且操作成本非常低。

The following are the locking stats during the column that are added with a constraint.

以下是在列期间添加了约束的锁定状态。

Resource Type

Resource Subtype

Request Mode

Records Count

DATABASE

S

1

DATABASE

DDL

S

1

KEY

X

11

METADATA

DATA_SPACE

Sch-S

1

OBJECT

IX

6

OBJECT

Sch-M

2

资源类型

资源子类型

请求模式

记录数

数据库

小号

1个

数据库

DDL

小号

1个

X

11

元数据

DATA_SPACE

Sch-S

1个

目的

6

目的

Sch-M

2

Please note that the following query should be executed in an open transaction in order to capture the above locking statistics.

请注意,以下查询应在打开的事务中执行,以捕获上述锁定统计信息。

SELECT
resource_type,
resource_subtype,
request_mode,
COUNT(*) FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
GROUP BY resource_type,
resource_subtype,
request_mode

This shows that Table (Object) has intended Exclusive lock which means that the table is not exclusively locked during the addition of the column. Also, adding a column with default value has not taken even a one minute though it has 500,000 records.

这表明表(对象)具有预期的排他锁,这意味着在添加列期间表未排它锁。 同样,添加具有默认值的列即使有500,000条记录,也花了一分钟的时间。

Let us see the table size.

让我们看看桌子的大小。

Table size after adding a column with default constraint using SQL Server ALTER TABLE clause.

You will see that nothing has changed.

您会看到什么都没有改变。

Let us see the file sizes of the database.

让我们看看数据库的文件大小。

database size and transaction log file after adding a column with default constraint using SQL Server ALTER TABLE Add statement.

Nothing much has changed to the data file as well as for the log file. All of these results indicate that adding a column with a default constraint will result in only a metadata change.

数据文件和日志文件没有任何变化。 所有这些结果表明,添加具有默认约束的列只会导致元数据发生变化。

用值更新 (Update with a Value)

Let us update the same column with a different value and let us get the same stats.

让我们用不同的值更新同一列,让我们获得相同的统计信息。

Resource Type

Request Mode

Records Count

DATABASE

S

1

OBJECT

X

1

资源类型

请求模式

记录数

数据库

小号

1个

目的

X

1个

The above table shows that the table is exclusively locked which means that the table is not accessible during the update.

上表显示该表被独占锁定,这意味着该表在更新期间不可访问。

Let us look at the table size.

让我们看看表的大小。

Table size after adding and updating the column,

The table has grown by some value as shown in the above figure.

该表已增长了一些值,如上图所示。

The following are the details for the query expenses captured from the SQL Profiler.

以下是从SQL事件探查器捕获的查询费用的详细信息。

CPU

29,781

Reads

9,188,986

Writes

527,436

Duration Mille Seconds

1,113,142

中央处理器

29,781

9,188,986

527,436

持续时间毫秒

1,113,142

Evidently, when updating a column for a large table, resource consumption is high.

显然,当更新大表的列时,资源消耗很高。

The following is the database file sizes when the column is added and updated the values.

以下是添加和更新列时的数据库文件大小。

database size and transaction log file after adding a column and updating the column.

These stats show that there is a remarkable difference between adding a column with a default value and adding a column and updating the column with a value later. During the column update, the transaction log will grow and exclusive locking will be placed on the table prohibiting any reads or writes to the table.

这些统计数据表明,添加具有默认值的列与添加列以及稍后更新具有值之间的区别显着。 在列更新期间,事务日志将增长,并且排他锁将放置在表上,以禁止对该表进行任何读取或写入。

What is the difference in these scenarios? Prior to the SQL Server 2012, when adding a column with default value will cause the same behavior. In SQL Server 2012 and onwards, this is no longer the situation, the column is added online to the table and no update occurs and it is only a metadata change.

在这些情况下有什么区别? 在SQL Server 2012之前,添加具有默认值的列将导致相同的行为。 在SQL Server 2012及更高版本中,这种情况不再存在,该列已在线添加到表中,并且没有更新发生,而只是元数据更改。

如何做到这一点 (How This is Achieved)

This is achieved by a somewhat very simple but novel approach. sys.system_internals_partition_columns DMV has two additional columns named has_default and default_value as shown below.

这是通过某种非常简单但新颖的方法来实现的。 sys.system_internals_partition_columns DMV具有另外两个名为has_defaultdefault_value的列,如下所示。

sys.system_internals_partition_columns dmv

So when the column added with a default value, it will not update the data page instead it will update this system table. When a row is updated, then the default value will be pushed to the table even if the default value column is not updated.

因此,当添加默认值的列时,它将不会更新数据页,而是会更新此系统表。 当更新一行时,即使默认值列未更新,默认值也会被推送到表中。

Now, the next question is what if the Default constraint is dropped just after it is created. In that scenario, still, the above setting will prevail hence the previously set default value will be kept.

现在,下一个问题是如果在创建默认约束后立即删除默认约束。 在这种情况下,仍然会使用上述设置,因此将保留先前设置的默认值。

结论
(Conclusion
)

We covered the basic syntax of SQL Server ALTER TABLE in this article and implemented it to add columns to an existing table.

我们在本文中介绍了SQL Server ALTER TABLE的基本语法,并实现了将其添加到现有表中的列。

Before SQL Server 2012, there was no difference between adding a column with the default and adding a column and updating it. Therefore, in the prior SQL Server 2012 era, rather than adding a column with a default constraint, it is better to add a column and updating with batches so that the table is not exclusively locked.

在SQL Server 2012之前,添加具有默认值的列与添加列并对其进行更新之间没有区别。 因此,在以前SQL Server 2012时代,与其添加具有默认约束的列,不如添加一个列并进行批处理更新,以使该表不被排他地锁定,这更好。

However, from SQL Server 2012 onwards, the approach has changed so that adding a column with default constraints is much better.

但是,从SQL Server 2012起,此方法已更改,因此添加具有默认约束的列要好得多。

翻译自: https://www.sqlshack.com/sql-server-alter-table-add-column-overview/

`ALTER TABLE`命令用于在SQL Server数据库中修改现有的表结构,包括添加、删除或更改字段。以下是关于如何使用`ALTER TABLE`修改字段的一些基本规则: ### 添加新字段 要向表中添加新的,可以使用以下语法: ```sql ALTER TABLE [表名] ADD [新字段名称] 数据类型; ``` 例如,如果有一个名为 `Employees` 的表,并想要添加一个新的名为 `DepartmentID` 的整数字段: ```sql ALTER TABLE Employees ADD DepartmentID INT; ``` ### 删除字段 要从表中删除某个字段,可以使用以下语法: ```sql ALTER TABLE [表名] DROP COLUMN [字段名]; ``` 例如,假设要从 `Employees` 表中删除 `SalaryHistory` 字段: ```sql ALTER TABLE Employees DROP COLUMN SalaryHistory; ``` 请注意,这将永久删除该字段及其所有数据。 ### 更改现有字段 你可以通过改变字段的数据类型、长度、精度、是否允许NULL值等属性来更新字段的信息。以下是基本的语法示例: ```sql ALTER TABLE [表名] MODIFY [字段名] 新的数据类型 [长度|精度]; ``` 例如,如果要将 `EmployeeID` 字段更改为更具描述性的文本字段并增加最大字符限制: ```sql ALTER TABLE Employees MODIFY EmployeeID VARCHAR(50); ``` ### 修改默认值 如果你需要设置或更改字段的默认值,可以这样做: ```sql ALTER TABLE [表名] ALTER COLUMN [字段名] 新的数据类型 DEFAULT 默认值; ``` 例如,为了给 `BirthDate` 字段设置默认值为当前日期: ```sql ALTER TABLE Employees ALTER COLUMN BirthDate DATE DEFAULT GETDATE(); ``` ### 关于外键约束和非唯一索引 当你修改字段为特定的数据类型时,可能会影响现有的外键约束或非唯一索引。确保在执行此类操作前检查依赖性,并可能需要调整相关的约束或重建索引来保持数据一致性。 ### 完整性和触发器 修改字段还可能影响到基于该字段的完整性约束(如UNIQUE, NOT NULL)或触发器。确保在设计更改时考虑到这些因素,并对受影响的部分进行相应的调整。 ### 示例查询 - 查询 ALTER TABLE 后的状态 为了验证修改后的表状态,可以运行以下查询: ```sql SELECT * FROM [表名]; ``` ### 相关问题: 1. 如果尝试更改无法更改的字段会怎样? 尝试更改无法更改的字段(如系统标识符字段,如 ID 或 PK 字段),将会导致错误。应避免直接修改这类字段,除非有合理的理由并充分理解其潜在影响。 2. SQL Server 中如何回滚 ALTER TABLE 操作? 使用 `ROLLBACK` 事务指令或者通过数据库恢复点进行回滚。 3. 如何避免在 ALTER TABLE 期间的并发冲突? 可以通过锁定表(如 `READ UNCOMMITTED`, `READ COMMITTED`, `REPEATABLE READ`, `SERIALIZABLE` 等)控制并发访问,或者在修改过程完成后及时解锁表以释放资源。 请记得,在实际操作之前,备份重要数据,并考虑在测试环境上进行实验性更改,确保不会意外地破坏生产数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值