在我们的数据库中,有一个用ANSI_NULLS OFF
创建的表。现在我们使用此表创建了一个视图。我们想为此视图添加聚簇索引。
创建聚簇索引时,它显示的错误就像无法创建索引一样,因为此特定表的ANSI_NULL已关闭。
此表包含大量数据。所以我想将此选项更改为ON而不会丢失任何数据。
有没有办法改变表来修改这个选项。请提出你的建议。
答案 0 :(得分:16)
这是cross posted on Database Administrators所以我也可以在这里发布我的答案,以帮助未来的搜索者。
可以使用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])来再次正确设置种子值。
答案 1 :(得分:2)
不幸的是,没有重新创建就没有办法做到这一点。您需要使用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
他们。{/ p>
答案 2 :(得分:0)
我尝试了上面推荐的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
使用上述内容:
我意识到如果在其他表中引用表,则删除表可能并不总是直截了当。在这种情况下,我的情况并非如此。我很幸运。