T-SQL: преобразование datatime2 в datetime для всех столбцов типа datetime2 - PullRequest
3 голосов
/ 19 сентября 2009

У меня есть база данных, заполненная столбцами 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'

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

Ответы [ 4 ]

5 голосов
/ 19 сентября 2009

... затем вы перебираете результаты с помощью CURSOR и динамически запускаете 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;
3 голосов
/ 31 марта 2011

Я знаю, что эта ветка старая, но сегодня я делаю то же самое и просто хотел предложить свою технику. Всякий раз, когда мне нужно сделать много операторов DDL, я создаю один TSQL, который генерирует необходимый TSQL, а затем просто копирую результаты в окно запроса и запускаю его. Вам не нужно писать весь код курсора, как @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 с параметром «Результаты в текст» вместо параметра «Результаты в сетку».

1 голос
/ 14 ноября 2017

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

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;
0 голосов
/ 27 января 2018

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

...