Требуется сделать это сегодня для всех пользовательских таблиц в схеме и не удовлетворен ни одним из существующих ответов. В частности, некоторые из моих столбцов datetime имели значения по умолчанию, которые на самом деле никому не нужны, но мешали командам ALTER TABLE. Поэтому я написал скрипт, который просто сбрасывает эти значения по умолчанию, а затем меняет столбцы. Он сохраняет обнуляемость и может обрабатывать имена, содержащие пробелы, дефисы и т. Д. Внимание, впоследствии он не воссоздает значения по умолчанию.
Если вы находитесь в той же ситуации, вы можете использовать этот стабильный и протестированный сценарий, который также гарантирует, что не будет тихого усечения переменной nvarchar (max), используемой для составления операторов DDL:
DECLARE @sql AS nvarchar(max)=N''
--1. "ALTER TABLE [Tablename] DROP CONSTRAINT [DF__Tablename__Colname__Obfuscation]"
SELECT @sql=CAST('' AS nvarchar(MAX))+@sql
+N'ALTER TABLE ['+o.[name]+N'] DROP CONSTRAINT ['+co.[name]+']'
FROM sysconstraints c
INNER JOIN sysobjects o ON o.[id]=c.[id]
INNER JOIN syscolumns col ON col.[id]=o.[id] AND col.colid=c.colid
INNER JOIN sysobjects co ON co.[id]=c.constid
WHERE col.xtype=61 --datetime
EXEC sp_executesql @sql
--2. change type of all datetime columns
SELECT @sql=N''
SELECT @sql=CAST('' AS nvarchar(MAX))+@sql
+N'ALTER TABLE ['
+convert(nvarchar(max),t.name)
+N'] ALTER COLUMN ['
+convert(nvarchar(max),c.name)
+N'] datetime2 '
+CASE WHEN c.is_nullable = 1 THEN N'' ELSE N'NOT' END
+N' NULL;'+convert(nvarchar(max),char(13)+char(10))
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types st ON st.system_type_id = c.system_type_id
WHERE st.name=N'datetime'
AND t.xtype=N'U' --user tables only
ORDER BY t.[name]
EXEC sp_executesql @sql
Он использует древние таблицы синтаксиса и схемы, поэтому он работает с SQL Server версии 2008 (которая была первой, поддерживавшей datetime2
) до 2016 года.