Renaming an existing column without downtime - sql-server

I want to rename a column in a table. I see two approaches
Use sp_rename() and modify stored procedures to refer to new name.
Create new column, copy data from old column to new column, modify stored procedure etc. to refer to new column, eventually drop old column.
We can't use #1 as renaming column might leave stored procedures broken and we cannot afford any downtime.
If we go with #2, there is possibility that both old and new columns would co-exist for sometime after the data is copied over from old to new column but before the stored procedures deployed to use the new column.
Is there any way to keep the new column in sync with any updates/insert/deletes done to old column?
Can the AFTER triggers help here? But triggers usually increase the transaction time, so may not be a favorable solution.
Can I replicate data between two columns of the same table?
Any other possible solutions?
Also does sp_rename() cleanly updates all the references to the column - like stored procedures, functions, indexes etc?

First confirm there are no references to the column from outside the database like application code directly querying the column without going through stored procedures.
Here is how I renamed the column without causing the downtime -
Add a new column besides the existing column. The new column has same data type as the old column but the new name.Also create indexes, modify replication etc. on the new column based on the use cases.
Modify all stored procedures writing (insert/update operations) to the old column to also insert/update in the new column.
Copy over the data from old column to the new column for the existing records. Step 2 and 3, together, now ensure that the new column will remain in sync with the old column.
Modify all stored procedures reading from the old column to now read from the new column.
Now that all code has transitioned to use new column, we need to clean up -
Modify stored procedures from earlier Step#2 to stop referring to old column.
Drop the old column.

You could rename your table and create a view using the old table name and have the view include an alias for your column.
SQLPrompt by redgate has a feature called Smart Rename which can rename a column and update all of the references to the new name.
From SQL Prompt 7 documentation:
SQL Prompt can create a script that allows you to rename objects in your database without breaking dependencies. You can rename the following:
Tables (including columns)
Views (including columns)
Stored procedures (including parameters)
Functions (including parameters)
When an object is renamed:
SQL Prompt also modifies any objects that reference, or are referenced by, the renamed object to ensure that dependency links are not broken.
If you have previously renamed an object using SQL Server Management Studio or Enterprise Manager Rename, or the T-SQL sp_rename command, the object definition will contain the original name.
Any objects that reference this original name are not updated.
To help you locate objects that reference objects that no longer exist, see Finding invalid objects.
The original permissions and extended properties of the object are preserved.

Related

Adding column at specific location vs at the end of data table

In SQL Server is adding a new column at the end of the table faster than adding it at a specific location?
I have to add 20 new columns to a table that already has 250 columns and roughly 2M records. The new columns are null, float columns. Adding single column took me more than 10 minutes. I'm looking for any way to speed up the process.
If you're using SSMS, you should know that under the hood it is creating a new table with new columns then inserting the data from the original table, redoing all the keys and constraints, dropping the old table and then renaming the new table to use the old table's name.
It is probably better practice to add the row at the end and you can use then T-SQL in an order you want for retrieval.
Another note, if you're not locking the db or don't put it in single user mode it will take longer to run.
tl;dr - do not add column at specific position unless you have time to waste
Are you using?:
ALTER TABLE table_name
ADD column_name datatype
Or are you using the SSMS designer? SSMS designer may drop and recreate the table (a temporary table is created to hold the data temporarily) - this may be why it is taking a longer time.

Add column VS Recreating table

I was going through some SQL Scripts a coworker had wrote to upgrade a table to a newer version. It was simply adding a new column to the table. However, instead of a
ALTER TABLE [Table] ADD [Column] [DataType]
statement, he instead made a copy of the table with the new column, repopulated it with the existing data, deleted the old table, renamed the new one to the old table, and then re-added all the indexes and relationships.
My question is, is there any benefit to doing this rather than the simple Alter statement or is there any difference?
I can't imagine all that work for practically no difference other than the column's ordinal position being in the desired place.
When you use the SSMS GUI, it will sometimes take this approach. One possible reasons for doing it this way is "Inserting" a column rather than "appending" a column. (if you want the column to appear before some already existing columns.) In that case, adding a column won't work.
Essentially, any time a simple addition of a new column to the end of the table isn't what you're looking for. But my guess is that he used the GUI to add the column and chose the "generate SQL script" option.
Just a couple of differences on how that would be different. Hope this helps!
Adding new column to existing table:
Pros:
No need to recreate indices and constraints on the existing table.
Data on existing column remains intact.
Cons:
Huge table that has millions of records will need to be updated for
the new column.
Recreating a New Table:
Pros:
No need to worry for any kind of limits (number of columns, total
size of table) in the RDBMS
Cons:
Recreate indices and constraints
Reload data for all columns

Changing columns to identity (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)

Sql Server - changing column from UniqueIdentifier to varchar(128) - backwards compatability?

I'm making changes to a Sql Server (2008) database to change an existing column type from a UUID to a varchar(128) - the column, we'll call it reference was originally used to save an ID of a reference project that provided more information about the data in the row, but now the business requirements have changed and we're just going to allow free-form text instead. There were no foreign keys setup against the column, so there won't be any breaking relationships.
My biggest concern at the moment is one of backwards compatibility with existing stored procedures. Unfortunately, the database is very big and very old, and contains hundreds of stored procs littered throughout the design. I'm very nervous about making a change which could potentially break existing stored procs.
I know this is a loaded question, but in general, can UUID columns be converted into varchar columns without deleterious effects? It seems like any existing stored proc which inserted into or queried on the UUID column would still work, given that UUIDs can be represented as strings.
I've tried performed the below steps and I didn't see any issues, so i think you can go ahead and change the column datatype:
Created the table with the column type as unique identifier.
Created the stored procedure to insert a value into that table through NewID() function.
Execute the stored procedure, and data was inserted without any issue.
Now, I changed the column type to varchar and again executed the stored procedure.
Procedure ran fine without any issue, and data was inserted.
So, the answer is Yes, you can change the column data type.

How to add a constant column when replicating a database?

I am using SQL Server 2000 and I have two databases that both replicate (transactional push subscription) to a single database. I need to know which database the records came from.
So I want to add a fixed column specified in the publication to my table so I can tell which database the row originated from.
How do I go about doing this?
I would like to avoid altering the main databases mostly due to the fact there are many tables I would need to do this to. I was hoping for some built in feature of replication that would do this for me some where. Other than that I would go with the view idea.
You could use a calculated column Use the following on the two databases:
ALTER TABLE TableName ADD
MyColumn AS 'Server1'
Then just define the single "master" database to use a VARCHAR column (or whatever you want) that you fill using the calculated columns value.
You can create a view, which adds the "constant" column, and use it as a replication source.
So the solution for me was to set up the replication publications to allow transformations and create a DTS package for each site that appends the siteid into the tables to keep the ids unique as I can't use guids.

Resources