在我们的数据库中有一个用ANSI_NULLS OFF
. 现在我们已经使用这个表创建了一个视图。我们想为这个视图添加一个聚集索引。
在创建聚集索引时,它会显示一个错误,例如无法创建索引,因为此特定表的 ANSI_NULL 已关闭。
该表包含大量数据。所以我想在不丢失任何数据的情况下将此选项更改为 ON。
有什么办法可以改变表来修改这个选项。请提出您的建议。
在我们的数据库中有一个用ANSI_NULLS OFF
. 现在我们已经使用这个表创建了一个视图。我们想为这个视图添加一个聚集索引。
在创建聚集索引时,它会显示一个错误,例如无法创建索引,因为此特定表的 ANSI_NULL 已关闭。
该表包含大量数据。所以我想在不丢失任何数据的情况下将此选项更改为 ON。
有什么办法可以改变表来修改这个选项。请提出您的建议。
这是在数据库管理员上交叉发布的,所以我也不妨从这里发布我的答案,以帮助未来的搜索者。
它可以通过使用ALTER TABLE ... SWITCH
.
下面的示例代码
/*Create table with option off*/
SET ANSI_NULLS OFF;
CREATE TABLE dbo.YourTable (X INT)
/*Add some data*/
INSERT INTO dbo.YourTable VALUES (1),(2),(3)
/*Confirm the bit is set to 0*/
SELECT uses_ansi_nulls, *
FROM sys.tables
WHERE object_id = object_id('dbo.YourTable')
GO
BEGIN TRY
BEGIN TRANSACTION;
/*Create new table with identical structure but option on*/
SET ANSI_NULLS ON;
CREATE TABLE dbo.YourTableNew (X INT)
/*Metadata only switch*/
ALTER TABLE dbo.YourTable SWITCH TO dbo.YourTableNew;
DROP TABLE dbo.YourTable;
EXECUTE sp_rename N'dbo.YourTableNew', N'YourTable','OBJECT';
/*Confirm the bit is set to 1*/
SELECT uses_ansi_nulls, *
FROM sys.tables
WHERE object_id = object_id('dbo.YourTable')
/*Data still there!*/
SELECT *
FROM dbo.YourTable
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
PRINT ERROR_MESSAGE();
END CATCH;
警告:当您的表包含 IDENTITY 列时,您需要重新设定 IDENTITY 值。SWITCH TO 将重置标识列的种子,如果您对标识没有 UNIQUE 或 PRIMARY KEY 约束(例如,在 SQL 2014 中使用 CLUSTERED COLUMNSTORE 索引时),您不会立即注意到它。您需要使用 DBCC CHECKIDENT ('dbo.YourTable', RESEED, [reseed value]) 再次正确设置种子值。
不幸的是,如果不重新创建,就没有办法做到这一点。您需要创建新表ANSI_NULLS ON
并在那里复制所有数据。
它应该是这样的:
SET ANSI_NULLS ON;
CREATE TABLE new_MyTBL (
....
)
-- stop all processes changing your data at this point
SET IDENTITY_INSERT new_MyTBL ON
INSERT new_MyTBL (...) -- including IDENTITY field
SELECT ... -- including IDENTITY field
FROM MyTBL
SET IDENTITY_INSERT new_MyTBL OFF
-- alter/drop WITH SCHEMABINDING objects at this point
EXEC sp_rename @objname = 'MyTBL', @newname = 'old_MyTBL'
EXEC sp_rename @objname = 'new_MyTBL', @newname = 'MyTBL'
-- alter/create WITH SCHEMABINDING objects at this point
-- re-enable your processes
DROP TABLE old_MyTBL -- do that when you are sure that system works OK
如果有任何依赖对象,它们将在您重命名新表后立即使用。但是,如果其中一些是WITH SCHEMABINDING
您需要的,DROP
并且CREATE
它们是手动的。
我尝试了上面推荐的 SWITCH 选项,但无法重新设置身份。我不知道为什么。
我使用了以下替代方法:
SET IDENTITY_INSERT TABLE_NAME ON
INSERT INTO TABLE_NAME (PK, col1, etc.)
SELECT PK, col1, etc.
FROM [Database_Snapshot].dbo.TABLE_NAME
SET IDENTITY_INSERT TABLE_NAME OFF
使用上述:
我意识到如果表在其他表中被引用,删除表可能并不总是那么简单。在这种情况下,我不是这种情况。我很幸运。