1

Using version:

Microsoft SQL Server 2008 R2 (SP3-OD) (KB3144114) - 10.50.6542.0 (Intel X86) 
Feb 22 2016 18:12:09 
Copyright (c) Microsoft Corporation
Standard Edition on Windows NT 5.2 <X86> (Build : )

I have a heavy table (135K rows), that I moved from another DB. It transferred with the [id] column being a standard int column instead of it being the key & seed column. When trying to edit that field to become an identity specification, with a seed value, its errors out and gives me this error:

Execution Timeout Expired.  
The timeout period elapsed prior to completion of the operation...

I even tried deleting that column, to try recreate it later, but i get the same issue.

Thanks

UPDATE:

Table structure:

CREATE TABLE [dbo].[tblEmailsSent](
    [id] [int] IDENTITY(1,1) NOT NULL,  -- this is what it should be. currently its just an `[int] NOT NULL`
    [Sent] [datetime] NULL,
    [SentByUser] [nvarchar](50) NULL,
    [ToEmail] [nvarchar](150) NULL,
    [StudentID] [int] NULL,
    [SubjectLine] [nvarchar](200) NULL,
    [MessageContent] [nvarchar](max) NULL,
    [ReadStatus] [bit] NULL,
    [Folder] [nvarchar](50) NULL,
 CONSTRAINT [PK_tblMessages] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO
Vladimir Baranov
  • 31,799
  • 5
  • 53
  • 90
kneidels
  • 956
  • 6
  • 29
  • 55
  • Are u using SqlCommand in C# or VB or working form SSMS directly ? – ahmed abdelqader Jun 18 '17 at 21:25
  • 2
    Don't use the SSMS UI to change table schema. This can be done more efficiently using T-SQL script, Post the DDL for your existing table if you need help with that. – Dan Guzman Jun 18 '17 at 21:29
  • Thanks guys. Yes, I was using SSMS. I have pasted the `CREATE` code in the question. This table weighs in at about 2.4GB right now ... Thank you. – kneidels Jun 19 '17 at 05:45

1 Answers1

3

I think that your question is a duplicate of Adding an identity to an existing column. That question above has an answer that should be perfect for your situation. I'll reproduce its essential part here below.


But before that, let's clarify why you see the timeout error.

You are trying to add the IDENTITY property to existing column. And you are using SSMS GUI for it. A simple ALTER COLUMN statement can't do it and even if it could, SSMS generates a script that creates a new table, copies over the data into the new table, drops the old table and renames the new table to the old name. When you do this operation via SSMS GUI it runs its scripts with a predefined timeout of 30 seconds.

ssms timeout

Of course, you can change this setting in SSMS and increase the timeout, but there is a much better way.

  1. Simple/lazy way

Use SSMS GUI to change the column definition, but then instead of clicking "Save", click "Generate Change Script" in the table designer.

ssms generate change script

Then save this script to a file and review the generated T-SQL code that GUI runs behind the scene.

You'll see that it creates a temp table with the required schema, copies data over, re-creates foreign keys and indexes, drops the old table and renames the new table.

The script itself is usually correct, but pay close attention to transactions in it. For some reason SSMS often doesn't use a single transaction for the whole operation, but several transactions. I'd recommend to manually review the script and make sure that there is only one BEGIN TRANSACTION at the top and one COMMIT in the end. You don't want to end up with a half-done operation with, say, a table where all indexes and foreign keys were dropped.

If it is a one-off operation, it could be enough for you. Your table is only 2.4GB, so it may take few minutes, but it should not be hours.

If you run the T-SQL script yourself in SSMS, then by default there is no timeout. You can stop it yourself if it takes too long.

ssms run


  1. Smart and fast way to do it is described in details in this answer by Justin Grant.

The main idea is to use the ALTER TABLE...SWITCH statement to make the change only touching the metadata without touching each page of the table.

BEGIN TRANSACTION;

-- create a new table with required schema
CREATE TABLE [dbo].[NEW_tblEmailsSent](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [Sent] [datetime] NULL,
    [SentByUser] [nvarchar](50) NULL,
    [ToEmail] [nvarchar](150) NULL,
    [StudentID] [int] NULL,
    [SubjectLine] [nvarchar](200) NULL,
    [MessageContent] [nvarchar](max) NULL,
    [ReadStatus] [bit] NULL,
    [Folder] [nvarchar](50) NULL,
 CONSTRAINT [PK_tblEmailsSent] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

-- switch the tables
ALTER TABLE [dbo].[tblEmailsSent] SWITCH TO [dbo].[NEW_tblEmailsSent];

-- drop the original (now empty) table
DROP TABLE [dbo].[tblEmailsSent];

-- rename new table to old table's name
EXEC sp_rename 'NEW_tblEmailsSent','tblEmailsSent';

COMMIT;

After the new table has IDENTITY property you normally should set the current identity value to the maximum of the actual values in your table. If you don't do it, new rows inserted into the table would start from 1.

One way to do it is to run DBCC CHECKIDENT after you switched the tables:

DBCC CHECKIDENT('dbo.tblEmailsSent')

Alternatively, you can specify the new seed in the table definition:

CREATE TABLE [dbo].[NEW_tblEmailsSent](
    [id] [int] IDENTITY(<max value of id + 1>, 1) NOT NULL,
Vladimir Baranov
  • 31,799
  • 5
  • 53
  • 90
  • Thank you for the detailed answer. I added the version to the OP. This is the error I got when trying to run solution #2: `ALTER TABLE SWITCH statement failed. The table 'dbo.NEW_tblEmailsSent' has clustered index 'PK_tblEmailsSent' while the table 'dbo.tblEmailsSent' does not have clustered index.` – kneidels Jun 22 '17 at 14:30
  • Well, the error message is clear - one table has a clustered index, another doesn't. Make sure that the definition of your new table is exactly the same as the existing table, except the `IDENTITY` part. Use SSMS to generate the `CREATE TABLE` script. – Vladimir Baranov Jun 22 '17 at 14:39
  • hmmm... getting `Caution: Changing any part of an object name could break scripts and stored procedures.` – kneidels Jun 22 '17 at 15:25
  • @kneidels, yes, this is a warning from `sp_rename`. The script that SSMS generates also uses `sp_rename`, but when you run it through GUI you don't see this warning. – Vladimir Baranov Jun 22 '17 at 23:31
  • How do I run it through GUI? Do you mean save the script and then run it? i thought the whole point of running the T-SQL, is thats its faster? – kneidels Jun 23 '17 at 06:20
  • @kneidels, I meant to say, that this warning comes from `sp_rename`. When you run T-SQL script yourself (open .sql file in SSMS and press `F5`), not using the GUI of the Table Designer, you see this warning. Together with other possible messages from each statement of the script. When you use GUI of the Table Designer, SSMS calls the same `sp_rename` behind the scenes, but Table Designer GUI doesn't show this warning to you. This warning is not a problem. You just see everything what is going on. – Vladimir Baranov Jun 23 '17 at 06:32
  • Thanks @vladimir - sorry. i am just not clear on how to run this script without getting the error? – kneidels Jun 24 '17 at 20:46
  • @kneidels, `Caution: Changing any part of an object name could break scripts and stored procedures.` is not an error, it is a warning. You can safely ignore it. You will see this warning any time you run `sp_rename`. – Vladimir Baranov Jun 25 '17 at 02:02
  • Hi again - i see the table is defined properly. Thanks again. Question: i see that even though my `[id]` primary key (now setup correctly) - its now counting from the number `1`, even though i have existing numbers going up to 130K+... is it over-writing? is it filling in blanks? – kneidels Jun 25 '17 at 09:41
  • @kneidels, the actual values stored in the table should not change. Do you mean that new rows inserted into the table get IDENTITY starting from 1? In this case you should fix the IDENTITY seed as shown in the answers to the question that I linked an the top of this answer. I've added it to my answer as well. – Vladimir Baranov Jun 25 '17 at 11:22