71

I have a UNIQUE, NON CLUSTERED index on a table that is currently using 4 columns for the index.

I want to create an alter script that can merely add another column to this index. The new column type is varchar.

The database is SQL Server 2005.

4
  • 2
    I'm sure I'm missing something but why can't you just use DROP INDEX Table.<Index>; CREATE UNIQUE INDEX <Index> ON Table (Col1, Col2, Col3, Col4) Commented Mar 19, 2012 at 7:57
  • @Lieven, I was thinking about this too. Is it possible to safely DROP and then CREATE the index with existing data in the table? Commented Mar 19, 2012 at 7:59
  • 1
    Yes. You can drop and create indexes at will. All you might notice is a drop in performance executing queries while the indexes are gone but dropping and creating a (none-clustered) index has no impact whatsoever on the actual data stored in your tables (Creating a clustered index impacts the physical ordering of your data but again, no data is lost) Commented Mar 19, 2012 at 8:11
  • Unless you have code somewhere that uses the index as a HINT Commented Feb 10 at 20:44

5 Answers 5

112

You cannot alter an index - all you can do is

  1. drop the old index (DROP INDEX (indexname) ON (tablename))

  2. re-create the new index with the additional column in it:

       CREATE UNIQUE NONCLUSTERED INDEX (indexname)
       ON dbo.YourTableName(columns to include)
    

The ALTER INDEX statement in SQL Server (see docs) is available to alter certain properties (storage properties etc.) of an existing index, but it doesn't allow changes to the columns that make up the index.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks Marc, your proposed solution worked, and script approved by DBA's on our team.
Now you've got me stumped... why ask the question if you have DBA's on your team?
Look into DROP_EXISTING in the Create Index page on MSDN. With certain restrictions, you can modify an index. See the reply by Paul White here. sqlservercentral.com/Forums/Topic913722-391-1.aspx
@LievenKeersmaekers why ask the question if you have DBA's on your team? For people having the same question maybe? Overall purpose of StackOverflow?
@LievenKeersmaekers - Code First ~ index(es) should be maintained in Migrations. Migrations written in a non-sql language. Programmers write migrations, not DBAs
4

I might be 9 years late but this is how I do it (this drops the existing index and creates the new one with the columns in the list):

CREATE UNIQUE NONCLUSTERED INDEX [INDEX_NAME] ON [TABLE_NAME]
(
    [COLUMN1] DESC,
    [COLUMN2] ASC
) 
WITH
(
    PAD_INDEX = OFF,
    STATISTICS_NORECOMPUTE = OFF,
    SORT_IN_TEMPDB = OFF,
    IGNORE_DUP_KEY = ON,
    DROP_EXISTING = ON,
    ONLINE = OFF,
    ALLOW_ROW_LOCKS = ON,
    ALLOW_PAGE_LOCKS = ON
) 
ON [PRIMARY]

Comments

3

If the new column you are adding to the index is on the end of the list of columns - in other words, if the column list of the old index is a prefix of the column list of the new index - then rows which are sorted by the old columns will still be sorted by the new columns. In Sybase SQL Server and perhaps older versions of Microsoft SQL Server, there was a with sorted_data option to let you declare that the rows were already sorted. But on MSSQL 2008 R2 it appears to have no effect; the option is accepted but silently ignored. In any case I think the option was mostly useful with clustered indexes.

Others mentioned with drop_existing, which sounds great, but is for more expensive versions of MSSQL only.

3 Comments

Where are you getting with sorted_data from? I don't see sorted_data listed as a with, aka "relational_index_option", of the create index Statement in the SQL Server 2008+ docs for that Statement (at: link).
with sorted_data is something I remember from the old days of Sybase SQL Server. Microsoft has removed some of the funky index creation options that Sybase supported, but not this one. However a quick experiment on MSSQL 2008 R2 shows that it may now be a no-op; no error is given if the data in the table isn't sorted. So I will revise my answer.
A quick search shows that the option was documented for MSSQL 2000.
0

I hope alter index means first we have to drop the index and create the index again

syntax:

if exists
(
select * from sys.indexes where name ='ix_name'
)
BEGIN
DROP INDEX Table.index name
END

IF NOT EXISTS
(
select * from sys.indexes where name ='ix_name'
)
BEGIN
CREATE NONCLUSTERED INDEX 
ON TABLENAME
(
COLUMN1,
COLUMN2,
COLUMN3,
COLUMN4,
--Whatever column u want to add
)
end
go

Comments

0

For UNIQUE keys, DROP may not work with any solutions above, so I add this option.

Delete the index from the table. In the tables list, for the table, for Keys, find the key, right click, select Delete and approve the deletion.

Then execute the create SQL, making sure DROP_EXISTING = OFF (because it does not exist anymore).

CREATE UNIQUE NONCLUSTERED INDEX [INDEX_NAME] ON [TABLE_NAME]
(
    [COLUMN1] DESC,
    [COLUMN2] ASC
) 
WITH
(
    PAD_INDEX = OFF,
    STATISTICS_NORECOMPUTE = OFF,
    SORT_IN_TEMPDB = OFF,
    IGNORE_DUP_KEY = ON,
    DROP_EXISTING = OFF,
    ONLINE = OFF,
    ALLOW_ROW_LOCKS = ON,
    ALLOW_PAGE_LOCKS = ON
) 
ON [PRIMARY]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.