改变表开关

lce*_*rni 5 sql-server-2012

我有两列要从计算转换为非计算。我有代码。但是,有人建议我使用 ALTER TABLE SWITCH。我相信建议它的人不想让数据库停机。我想他们想要这样的东西 1)创建新文件组 2)创建新的重复表,它在新文件组上有计算列 3)将计算列更改为非计算列 4)切换数据库以使用这个新文件组/表 5) 删除带有计算列的旧文件组/表

但是,当我研究 ALTER TABLE SWITCH 命令时,在我看来,这种情况不是它的正确用法。

有没有办法使用 ALTER TABLE SWITCH 将计算列更改为非计算列?

Mar*_*ith 5

ALTER TABLE ... SWITCH 有时可能对此类事情有用。

具体来说,它可以允许将具有IDENTITY列的大表切换到具有相同结构但没有IDENTITY列的不同表,因此(在删除和重命名之后)有效地允许IDENTITY属性作为元数据更改(示例)进行切换。

使用下表

CREATE TABLE T1
(
Foo int,
Bar as CAST(''  AS CHAR(100)) PERSISTED
)

CREATE TABLE T2
(
Foo int,
Bar  CHAR(100) NULL
)
Run Code Online (Sandbox Code Playgroud)

T2 表元数据将与 T1 表的物理布局兼容,因此只进行元数据切换会很好,但实际上它不起作用。

ALTER TABLE T1 SWITCH TO T2
Run Code Online (Sandbox Code Playgroud)

消息 4965,级别 16,状态 1,第 17 行 ALTER TABLE SWITCH 语句失败。表 'tempdb.dbo.T1' 中的列 'Bar' 是计算列,但未计算 'tempdb.dbo.T2' 中的同一列。

以下也不起作用

ALTER TABLE T1
  ALTER COLUMN Bar CHAR(100) NULL 
Run Code Online (Sandbox Code Playgroud)

无法更改“Bar”列,因为它是“COMPUTED”。

如果保持桌子在线是主要优先事项,那么您可能需要考虑。

  • 添加两个可空列,最终将替换计算列(仅元数据更改)。
  • 小批量更新新列(以避免长时间持有或升级锁),直到完成整个表。
  • 以可重复读取开始事务
  • 获取共享表锁
  • 新列的值需要更新的任何行的最终同步,因为它自批处理以来已经过时。
  • 删除计算列
  • 重命名替换
  • 提交交易


Ken*_*her 2

我相信他们所说的是分区开关。这并不是您在这里寻找的东西。它非常适合将数据快速加载到表中(从用户的角度来看),但实际上不适用于整个表。

如果我是你,我会改名。

  1. 创建一个新表TableName_New,其中计算列只是常规列。确保保留所有索引、约束、外键、权限等。您可能希望在步骤 2 之后应用任何非聚集索引。
  2. 将旧表中的数据加载到新表中。如果它是活动表,您必须记下停止的位置,以便可以在交换后加载剩余数据。
  3. 进行重命名交换

    EXEC sp_rename 'TableName','TableName_Old';
    EXEC sp_rename 'TableName_New','TableName';
    
    Run Code Online (Sandbox Code Playgroud)
  4. 将剩余的行(在步骤 2 开始和步骤 3 结束之间创建的)移动到 中TableName