【问题标题】:Safely add a non-null column to an existing table安全地将非空列添加到现有表
【发布时间】:2020-02-12 04:19:24
【问题描述】:
IF NOT EXISTS(SELECT 1 FROM sys.columns 
              WHERE Name = N'MyColumn' AND Object_ID = Object_ID(N'[MySchema].[MyTable]'))
    ALTER TABLE [MySchema].[MyTable] 
        ADD [MyColumn] VARCHAR(10) NULL
GO

UPDATE [MySchema].[MyTable] 
SET [MyColumn] = 'ValueForExistingData' 
WHERE [MyColumn] IS NULL

ALTER TABLE [MySchema].[MyTable] 
    ALTER COLUMN [MyColumn] VARCHAR(10) NOT NULL

需要什么样的锁定/事务隔离级别来确保不会在UPDATEALTER COLUMN 语句之间插入新行?这是为了防止ALTER COLUMN 语句由于新插入行中MyColumn 中的NULL 值而失败。

是否有更好的替代 GO 以确保 ADD [MyColumn]SET [MyColumn] 之前完成?

【问题讨论】:

标签: sql sql-server


【解决方案1】:

您可以使用以下语法:

BEGIN TRANSACTION

ALTER TABLE [MySchema].[MyTable] 
        ADD [MyColumn] VARCHAR(10) NOT NULL CONSTRAINT MyTableDefault DEFAULT 'ValueForExistingData';

ALTER TABLE [MySchema].[MyTable] 
        DROP CONSTRAINT MyTableDefault;

COMMIT

在企业版 SQL Server 2012+ 上,这两个语句都将是仅元数据操作,因此您不必更新所有数据页,整个操作只需几毫秒。

【讨论】:

  • 第一个是否仅为元数据取决于 SQL Server 的版本。他们需要将企业版用于本地版本。无论如何,它仍然按照他们的要求进行
【解决方案2】:

您可以设置默认约束以确保所有现有列都具有现有数据的值。

然后删除默认约束以强制新行具有输入的值。

IF NOT EXISTS(SELECT 1 FROM sys.columns 
              WHERE Name = N'MyColumn' AND Object_ID = Object_ID(N'[MySchema].[MyTable]'))
    ALTER TABLE [MySchema].[MyTable] 
        ADD [MyColumn] VARCHAR(10) NOT NULL DEFAULT 'ValueForExistingData';
GO

ALTER TABLE [MySchema].[MyTable] 
ALTER COLUMN [MyColumn] DROP DEFAULT;
GO

https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql

【讨论】:

    猜你喜欢
    • 2015-03-19
    • 2019-02-18
    • 2021-12-10
    • 2021-08-08
    • 1970-01-01
    • 2011-07-31
    • 2016-11-13
    • 1970-01-01
    相关资源
    最近更新 更多