Changing columns to identity (SQL Server) - sql-server

My company has an application with a bunch of database tables that used to use a sequence table to determine the next value to use. Recently, we switched this to using an identity property. The problem is that in order to upgrade a client to the latest version of the software, we have to change about 150 tables to identity. To do this manually, you can right click on a table, choose design, change (Is Identity) to "Yes" and then save the table. From what I understand, in the background, SQL Server exports this to a temporary table, drops the table and then copies everything back into the new table. Clients may have their own unique indexes and possibly other things specific to the client, so making a generic script isn't really an option.
It would be really awesome if there was a stored procedure for scripting this task rather than doing it in the GUI (which takes FOREVER). We made a macro that can go through and do this, but even then, it takes a long time to run and is error prone. Something like: exec sp_change_to_identity 'table_name', 'column name'
Does something like this exist? If not, how would you handle this situation?
Update: This is SQL Server 2008 R2.

This is what SSMS seems to do:
Obtain and Drop all the foreign keys pointing to the original table.
Obtain the Indexes, Triggers, Foreign Keys and Statistics of the original table.
Create a temp_table with the same schema as the original table, with the Identity field.
Insert into temp_table all the rows from the original table (Identity_Insert On).
Drop the original table (this will drop its indexes, triggers, foreign keys and statistics)
Rename temp_table to the original table name
Recreate the foreign keys obtained in (1)
Recreate the objects obtained in (2)

Related

SQL DB Diagram Extract

I am using SQL Server 2011 and need to create a visual representation (diagram). The current structure has no relationships (Foreign Keys) between tables and there are tables without any Primary Keys.
I have tried using SQL Database Diagrams but can't add any relationship between tables without the change happening on the DB itself.
I want to draw relationships without it making any changes.
Are there any free DB Diagram software that I can use in order to achieve this? I have tried DbVisualizer but getting same issues as with the diagram within SQL.
In your case I would do the following:
Generate scripts for your database (schema only) (as #Serg suggested already)
You can do this using SSMS: Right click your database - Tasks - Generate Scripts. Select all tables and then under Advanced, select Schema only at the Types of data to script. Save script and run it in some test environment to generate a schema only copy of your database. (If doing this on the same server, you might need to change the script a little, to give the new database another name)
Dynamically try to "guess" the foreign key relationships
Since you have 500+ tables, you could try to make this script work for
you (of course it would need some testing and tuning to adapt it for your
case) but I used it in the following scenario and it worked.
Hopefully you do have a naming convention. In this script it is assumed that the referenced keys are named the same, but this can be configured.
So, I created the following tables:
CREATE TABLE test (testid int identity(1,1) UNIQUE, description varchar(10))
CREATE TABLE test_item (id int identity(1,1) UNIQUE, testid int)
And the following indexes on their primary keys (normally, you should have them too)
CREATE CLUSTERED INDEX [ix_testid] ON [dbo].[test]([testid] ASC)
CREATE CLUSTERED INDEX [ix_testitemid] ON [dbo].[test_item]([id] ASC)
I did not create a foreign key relationship.
Next I ran the script from the Automatically guessing foreign key constraints article and I managed to get the following result:
Executing all the ALTER statements generated from this script you could get your relationships created in your new database - generate the diagram from this database and you are done! :)
ps. I would suggest you test it out step by step, for example with one table first and then adding others and checking the results.
You can try a working demo of my little test here.
Good luck!

Autoincrement in Entity Framework 5 without identity column in database

I have not been able to find any appropriate solution for my problem, so here's my question for you:
In Entity Framework (5.0), how can I setup an ID-column (PK) to be autocremented when no identity column is defined in the actual database (SQL Server 2005)?
I have seen the StoreGeneratedPattern, but not sure how this would work without identity in the db. The manual approach would be to manually populate the POCO with MAX(id)+1, but that feels like a hack and I'm worried that it will introduce problems in a multi-threaded environment where multiple requests may insert records to my table at the "same" time.
Note that I do not have the possibility to alter the table schema in the database.
What's the best way to solve this?
If one instance of your application is the only thing inserting rows into this table, then the MAX(Id) + 1 hack is probably good enough. Otherwise, you'll need to alter the database schema to generate these values on insert -- either by using IDENTITY or by re-inventing the wheel using triggers, sprocs, etc.
Whatever your solution, it should guarantee that a duplicate key will never be generated -- even if a transaction happens to rollback one or more inserts.
If nothing else inserts into the table, you should be able to alter Id to an identity column without breaking compatibility.
FYI: Entity Framework's StoreGeneratedPattern (or DatabaseGeneratedOption) only specifies how values are handled on insert and update. Using Identity tells EF that the value is expected to be generated by the database on insert. Computed means it's generated on both insert and update.

SQL Server Mgmt Studio messing up my Database!

This has effectively ruined my day. I have a larger number of tables with many FK relationships in between. One of the tables (lets call it table A) has a computed column, which is computed via a UDF with schemabinding and is also fulltext indexed.
If I edit any table (lets call it table B) that in any way is related (e.g via FK) to the table with the fulltext indexed computed column (table A), and I save it, the following happens:
Changes to the table (table B) are saved
I get the error: "Column 'abcd' is no fulltext indexed." regarding table A which I didn't even edit, and then "User canceled out of save dialog"
All FK relationships to ALL TABLES from Table B are DELETED
What the hell is going on??? Can someone explain to me how this can happen?
I've had the same kind of problem. As Will A said, the management studio will do the following steps to update a table and its foreign keys:
Create a new table called temp_
Copy contents from old table into new
Drop all constraints, indexes and foreign keys
Drop old table
Rename new table to be = old table
Recreate the foreign keys, indexes and constraints
I may have the first 3 in the wrong order but you get the idea.
In my case I've lost entire tables not just the foreign keys. Personally I don't like the way it does it as it can be VERY time consuming to have to recreate indexes on a table with lots of data in. If its a small change I usually do it myself in T-SQL.
Review the change script before it executes it, make sure it looks sensible.
#OMGPonies, why can't you drop a foreign key if there is data in the table? Of course you can. There are only restrictions on creating foreign keys on tables with data but that is only if it breaks the constraint. However even that can be avoided by using the WITH NOCHECK option when creating the key. Yes I know it'll break when you try to update a broken result set.

Making primary key and identity column after data has been loaded

I have quick question for you SQL gurus. I have existing tables without primary key column and Identity is not set. Now I am trying to modify those tables by making existing integer column as primary key and adding identity values for that column. My question is should I first copy all the records from the table to a temp table before making those changes . Do I loose all the previous records if I ran the T-SQL commnad to make primary key and add identity column on those tables. What are the approaches should I take such as
1) Create temp table to copy all the records from the table to be modified
2) Load all the records to the temptable
3) Make changes on the table schema
4) Finally load the records from the temp table to the original table.
Or
there are better ways that this? I really appreciate your help
Thanks
Tools>Options>Designers>Table and Database Designers
Uncheck "Prevent saving changes that require table re-creation"
[Edit] I've tried this with populated tables and I didn't lose data, but I don't really know much about this.
Hopefully you don't have too many records in the table. What happens if you use Management studio to change an existing field to identity is that it creates another table with the identity field set. it turns identity insert on and inserets the records from the original table, then turns identity insert off. Then it drops the old table and renames the table it just created. This can be quite a lengthy process if you have many records. If so I would script this out and then do it in a job that runs during the off hours because the table will be completely locked while you do this.
just do all of your changes in management studio, copy/paste the generated script into a file. DON'T SAVE CHANGES at this point. Look over and edit that script as necessary, it will probably do almost exactly what you are thinking (it will drop the original table and rename the temp one to the original's name), but handle all constraints and FKs as well.
If your existing integer column is unique and suitable, there should be no problem converting it to a PK.
Another alternative, if you don't want to use the existing column, you can add a new PK columns to the main table, populate it and seed it, then run update statements to update all other tables with new PK.
Whatever way you do it, make sure you do a back-up first!!
You can always add the IDENTITY column after you have finished copying your data around. You can also then reset the IDENTITY seed to the max integer + 1. That should solve your problems.
DBCC CHECKIDENT ('MyTable', RESEED, n)
Where n is the number you want the identity to start at.

SQLSERVER: How to alter an existing table int primary key to become an identity column?

My database has a table with thousands of records. The primary key is an integer. There's a lot of foreign key constraints associated with this column.
I want to change this column to become an identity key. What's the best way to do it? I also need to send this update to our clients installations.
Bonus points for an answer that works in Sql Server 2000.
There's a great feature in SQL Server Management Studio that saved my day.
In SSMS go to Options -> Designers -> Table and Database Designers, check "Auto generate change scripts" and uncheck "Prevent saving changes that require table re-creation".
In object explorer, go to your table and select the column that will get the Identity specification. Right click and select modify. In the Column properties panel, expand the tree "Identity Specification" and change "(Is Identity)" to yes. Now on the upper left size, select the icon "Generate script". Pay attention to the warning messages.
Now you will have a generated script that will drop all your constraints, recreate the table with identity, and recreate the constraints. WOW!
I'll test it and post here my results.
Update: Everything worked fine. I forgot to say in the question that I need the script to reproduce the modification in our clients installations.
In Enterprise Manager, right click the table in table view, select design.
click the left hand side of the column (then, double click identity, in columns underneath, in column properties, turns it on, defaults to auto increment 1
There is no single "ALTER TABLE" DDL for changing an existing column to an identity column. You can only add a new identity column to an existing table.
This can be done in Enterprise Manager but you need to be aware that Sql server is creating a new table and copying you data across in the background. You may have some issues with this. Here is an article that explains this a bit more http://www.mssqltips.com/tip.asp?tip=1397
In your scenario i think you will need a combination of this script and something to disable and reenable your fk's.
If the column is an integer as a part of existing relationships then it is already unique. Therefore you do not have to worry about duplicates! That's one huge hassle avoided already.
You can either issue an ALTER TABLE command to change the column or you can do it with Enterprise Manager.

Resources