I want to change my column data type from "Datetime" to "Datetime2(7)". If I try to do it with the GUI SQL Server 2014 asks to save all FKs table dependencies and then I get a lock timeout because this table has millions of rows. Is this possible while not losing the FKs dependencies and any data?
It is a Test environment. The reason I want to do this is because I think I'm getting locks because of datetime precision (milliseconds). I have many rows with the same datetime and not ordered.
Best Answer
It's possible to change the data type without data loss or breaking FK dependencies. It depends on whether you have some downtime where you can execute the required change though.
Changing from
datetime
todatetime2(7)
will require every row in the table / indexes to be updated, since these two types are stored differently on disk. This can take a little time, depending on how many rows your table has (you said "millions").The change would look like this in T-SQL (you should definitely do things like this in T-SQL rather than the GUI, by the way):
The
ALTER
statement here requires SCH-M (schema modification) locks: on the table being changed, and on the tables that have foreign key relationships to this one. That means that this statement will wait until there are no concurrent transactions before it's able to run.Once it starts running, it will also block any concurrent activity on the tables until it completes.
Here's a toy example that creates a table with 10,000,000 rows with dates, and another table with 1,000 rows referencing the first table:
That code takes about 30 seconds to run on my machine. With no other concurrent activity, the
ALTER
statement takes about 10-15 seconds:Ideally, you could do this kind of thing on a test system to assess about how long the blocking will be in production once the
ALTER
begins.Regarding my "concurrent activity" statements, if I open a transaction and update a row in
dbo.DateTest
, theALTER
won't even start. It sits and waits on the SCH-M lock that it needs, which you can see by runningsp_WhoIsActive @get_locks = 1
:If I commit or rollback that update transaction, the
ALTER
starts, and I can see that it takes out locks on theDateTest
andOtherTable
tables (abbreviated XML here):This will block writes on the tables involved until the
ALTER
completes.