Pregunta

Tengo una base de datos llena de columnas datetime2 que necesita ser movida a una base de datos SQL 2005. Entonces, necesito convertir todas estas columnas datetime2 (7) a datetime.

¿Cómo puedo hacer esto?

En este momento, he logrado seleccionar el nombre de la tabla y el nombre de la columna para todas las columnas con el tipo de datos datetime2 como este:

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'

Simplemente no sé cómo hacer el resto.

¿Fue útil?

Solución

... luego itera sobre sus resultados con el CURSOR y ejecuta dinámicamente el DDL como:

ALTER TABLE myTable ALTER COLUMN myColumn datetime [NOT] NULL

para que obtenga algo similar a esto (no probado):

Editar: también se agregó verificación de capacidad nula:

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;

Otros consejos

Sé que este hilo es antiguo, pero hoy estoy haciendo lo mismo y solo quería ofrecer mi técnica. Cada vez que necesito hacer muchas declaraciones DDL, creo un TSQL que genera el TSQL que se necesita y luego simplemente copio los resultados en la ventana de consulta y lo ejecuto. No necesita escribir todo el código del cursor como sugerencia @van (aunque eso funciona bien).

Entonces, para su situación, simplemente ejecute la instrucción sql:

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

Luego, copie los resultados en una nueva ventana de consulta y ejecútelo. A veces necesita agregar declaraciones " GO " en su propia línea entre comandos. Si es así, agregue char (13) + 'GO' en su cadena de salida.

Además, asegúrese de ejecutar la consulta en SQL Mgmt Studio con los "Resultados a texto" opción en lugar de " Resultados a la cuadrícula " opción.

Se mejoró la respuesta anterior para atender los esquemas

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;

Necesitaba hacer esto hoy para todas las tablas de usuario en un esquema, y ??no estaba satisfecho con ninguna de las respuestas existentes. Especialmente, algunas de mis columnas de fecha y hora tenían valores predeterminados, que en realidad nadie necesitaba, pero obstaculizaban los comandos ALTER TABLE. Entonces escribí un script que simplemente elimina esos valores predeterminados y luego cambia las columnas. Conserva la nulabilidad y puede manejar nombres que contienen espacios, guiones, etc. Precaución, no recrea los valores predeterminados posteriormente.

Si está en la misma situación, puede usar este script estable y probado, que también asegura que no haya un truncamiento silencioso de la variable nvarchar (max) utilizada para componer las declaraciones 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

Utiliza tablas de sintaxis y esquema antiguas, por lo que funciona desde la versión 2008 de SQL Server (que fue la primera en admitir datetime2 ) hasta 2016.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top