sqlsql-server-2008clustered-indexansi-nulls

Update ANSI_NULLS option in an existing table


In our database there is a table which is created with ANSI_NULLS OFF. Now we have created a view using this table. And we want to add a clustered index for this view.

While creating the clustered index it is showing an error like can't create an index since the ANSI_NULL is off for this particular table.

This table contains a large amount of data. So I want to change this option to ON without losing any data.

Is there any way to alter the table to modify this option . Please give your suggestions.


Solution

  • This was cross posted on Database Administrators so I might as well post my answer from there here too to help future searchers.

    It can be done as a metadata only change (i.e. without migrating all the data to a new table) using ALTER TABLE ... SWITCH.

    Example code below

    /*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; 
    

    WARNING: when your table contains an IDENTITY column you need to reseed the IDENTITY value. The SWITCH TO will reset the seed of the identity column and if you do not have a UNIQUE or PRIMARY KEY constraint on the identity (e.g. when using CLUSTERED COLUMNSTORE index in SQL 2014) you won't notice it right away. You need to use DBCC CHECKIDENT ('dbo.YourTable', RESEED, [reseed value]) to correctly set the seed value again.