T-SQL:Преобразуйте datatime2 в datetime для всех столбцов типа datetime2

StackOverflow https://stackoverflow.com/questions/1446775

  •  22-07-2019
  •  | 
  •  

Вопрос

У меня есть база данных, полная столбцов datetime2, которые необходимо переместить в базу данных SQL 2005.Итак, мне нужно преобразовать все эти столбцы datetime2 (7) в datetime.

Как я могу это сделать?

Прямо сейчас мне удалось выбрать имя таблицы и имя столбца для всех столбцов с типом данных datetime2 следующим образом:

SELECT t.name, c.name, i.DATA_TYPE
FROM sys.tables AS t
JOIN sys.columns c ON t.object_id = c.object_id
JOIN information_schema.columns i ON i.TABLE_NAME = t.name AND i.COLUMN_NAME = c.name
WHERE i.data_type = 'datetime2'

Я просто не знаю, как сделать все остальное.

Это было полезно?

Решение

...затем вы перебираете свои результаты с помощью КУРСОРА и динамически запускаете DDL следующим образом:

ALTER TABLE myTable ALTER COLUMN myColumn datetime [NOT] NULL

так что вы получите что-то похожее на это (не тестировалось):

Редактировать:также добавлена проверка нулевой способности:

DECLARE @SQL AS NVARCHAR(1024)
DECLARE @TBL AS NVARCHAR(255)
DECLARE @COL AS NVARCHAR(255)
DECLARE @NUL AS BIT
DECLARE CUR CURSOR FAST_FORWARD FOR
    SELECT  t.name, c.name, c.is_nullable
    FROM    sys.tables AS t
    JOIN    sys.columns c ON t.object_id = c.object_id
    JOIN    information_schema.columns i ON i.TABLE_NAME = t.name AND i.COLUMN_NAME = c.name
    WHERE   i.data_type = 'datetime2'
    ORDER BY t.name, c.name

OPEN CUR
FETCH NEXT FROM CUR INTO @TBL, @COL, @NUL
WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @SQL = 'ALTER TABLE ' + @TBL + ' ALTER COLUMN ' + @COL + ' datetime' + (CASE WHEN @NUL=1 THEN '' ELSE ' NOT' END) + ' NULL;'
    EXEC sp_executesql @SQL
    FETCH NEXT FROM CUR INTO @TBL, @COL, @NUL
END

CLOSE CUR;
DEALLOCATE CUR;

Другие советы

Я знаю, что эта ветка старая, но я делаю то же самое сегодня и просто хотела предложить свою технику. Всякий раз, когда мне нужно сделать много операторов DDL, я создаю один TSQL, который генерирует необходимый TSQL, а затем просто копирую результаты в окно Query и запускаю его. Вам не нужно писать весь код курсора, как @van рекомендации (хотя это работает нормально).

Итак, для вашей ситуации просто запустите оператор sql:

select 'ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name + ' datetime [NOT] NULL' 
from INFORMATION_SCHEMA.columns 
where data_type = 'datetime2(7)'.

Затем скопируйте результаты в новое окно запроса и запустите его. Иногда вам нужно добавить операторы " GO " на отдельной строке между командами. Если это так, добавьте char (13) + 'GO' в вашу строку вывода.

Кроме того, обязательно запустите запрос в SQL Mgmt Studio с " Результаты в текст " параметр вместо "Результаты в таблицу" вариант.

Улучшен приведенный выше ответ для обслуживания схем

DECLARE @SQL AS NVARCHAR(1024)
DECLARE @TBL AS NVARCHAR(255)
DECLARE @COL AS NVARCHAR(255)
DECLARE @SCH AS NVARCHAR(255)
DECLARE @NUL AS BIT
DECLARE CUR CURSOR FAST_FORWARD FOR
    SELECT  t.name AS TableName, c.name ColumnName, s.name AS SchemaName, c.is_nullable
    FROM    sys.tables AS t
    JOIN    sys.columns c ON t.object_id = c.object_id
    JOIN    information_schema.columns AS i ON i.TABLE_NAME = t.name AND i.COLUMN_NAME = c.name
    JOIN    sys.schemas AS s on t.schema_id = s.schema_id
    WHERE   i.data_type = 'datetime2'    
    ORDER BY t.name, c.name

OPEN CUR
FETCH NEXT FROM CUR INTO @TBL, @COL, @SCH, @NUL
WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @SQL = 'ALTER TABLE ['+@SCH+'].[' + @TBL + '] ALTER COLUMN [' + @COL + '] datetime' + (CASE WHEN @NUL=1 THEN '' ELSE ' NOT' END) + ' NULL;'
    EXEC sp_executesql @SQL
    FETCH NEXT FROM CUR INTO @TBL, @COL,@SCH, @NUL
END

CLOSE CUR;
DEALLOCATE CUR;

Требуется сделать это сегодня для всех пользовательских таблиц в схеме и не удовлетворен ни одним из существующих ответов. В частности, некоторые из моих столбцов 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 года.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top