Domanda

Ho un database pieno di colonne datetime2 di quelle che devono essere spostate in un database SQL 2005. Quindi, ho bisogno di convertire tutte queste colonne datetime2 (7) in datetime.

Come posso fare per fare questo?

In questo momento sono riuscito a selezionare il nome della tabella e il nome della colonna per tutte le colonne con il tipo di dati datetime2 in questo modo:

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'

Non so proprio come fare il resto.

È stato utile?

Soluzione

... quindi ripeti i risultati con CURSOR ed esegui dinamicamente il DDL come:

ALTER TABLE myTable ALTER COLUMN myColumn datetime [NOT] NULL

in modo da ottenere qualcosa di simile a questo (non testato):

Modifica: aggiunta anche la verifica dell'abilità nulla:

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;

Altri suggerimenti

So che questo thread è vecchio ma oggi sto facendo la stessa cosa e volevo solo offrire la mia tecnica. Ogni volta che devo fare molte affermazioni DDL creo un TSQL che genera il TSQL necessario e quindi copia i risultati nella finestra Query ed eseguilo. Non è necessario scrivere tutto il codice cursore come suggerimento @van (anche se funziona bene).

Quindi, per la tua situazione, esegui semplicemente l'istruzione sql:

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

Quindi, copia i risultati in una nuova finestra di query ed eseguilo. A volte è necessario aggiungere le istruzioni " GO " sulla propria riga tra i comandi. In tal caso, aggiungi char (13) + 'GO' nella stringa di output.

Inoltre, assicurati di eseguire la query in SQL Mgmt Studio con " Risultati in testo " al posto dell'opzione " Risultati da griglia " opzione.

Migliorata la risposta sopra per soddisfare gli schemi

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;

Necessario eseguire questa operazione oggi per tutte le tabelle utente in uno schema e non era soddisfatto delle risposte esistenti. Soprattutto, alcune delle mie colonne del datetime avevano valori predefiniti, che in realtà nessuno aveva bisogno, ma ostacolavano i comandi ALTER TABLE. Quindi ho scritto una sceneggiatura che lascia cadere quelle impostazioni predefinite e quindi cambia le colonne. Conserva la nullità e può gestire nomi contenenti spazi, trattini, ecc. Attenzione, in seguito non ricrea i valori predefiniti.

Se ti trovi nella stessa situazione, puoi utilizzare questo script stabile e testato, che assicura anche che non vi sia troncamento silenzioso della variabile nvarchar (max) utilizzata per comporre le istruzioni 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

Utilizza antiche tabelle di sintassi e schemi, quindi funziona da SQL Server versione 2008 (che è stata la prima a supportare datetime2 ) fino al 2016.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top