Question

J'ai une base de données remplie de colonnes datetime2 qu'il est nécessaire de déplacer vers une base de données SQL 2005. J'ai donc besoin de convertir toutes ces colonnes datetime2 (7) en datetime.

Comment puis-je m'y prendre?

À l'heure actuelle, j'ai réussi à sélectionner le nom de la table et le nom de la colonne pour toutes les colonnes avec le type de données datetime2 comme ceci:

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'

Je ne sais tout simplement pas comment faire le reste.

Était-ce utile?

La solution

... alors vous parcourez vos résultats avec le CURSEUR et exécutez dynamiquement le DDL comme:

ALTER TABLE myTable ALTER COLUMN myColumn datetime [NOT] NULL

afin que vous obteniez quelque chose de similaire à ceci (non testé):

Modifier: ajout d'une vérification de la nullité:

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;

Autres conseils

Je sais que ce fil est vieux, mais je fais la même chose aujourd'hui et je voulais juste offrir ma technique. Chaque fois que j'ai besoin de faire beaucoup d'instructions DDL, je crée un TSQL qui génère le TSQL requis, puis copiez simplement les résultats dans la fenêtre de requête et exécutez-le. Vous n'avez pas besoin d'écrire tout le code du curseur comme @van suggestion (bien que cela fonctionne très bien).

Dans votre cas, exécutez simplement l'instruction SQL:

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

Ensuite, copiez les résultats dans une nouvelle fenêtre de requête et exécutez-les. Parfois, vous devez ajouter des instructions & GO; " sur leur propre ligne entre les commandes. Si tel est le cas, ajoutez char (13) + 'GO' dans votre chaîne de sortie.

Assurez-vous également que la requête est exécutée dans SQL Mgmt Studio avec l'option "Résultats en texte". option à la place de l'option "Résultats de la grille" option.

Amélioration de la réponse ci-dessus pour prendre en charge les schémas

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;

Nécessaire de le faire aujourd'hui pour toutes les tables utilisateur d'un schéma et n'était satisfait d'aucune des réponses existantes. Surtout, certaines de mes colonnes datetime avaient des valeurs par défaut, dont personne n’avait besoin, mais gênaient les commandes ALTER TABLE. J'ai donc écrit un script qui supprime simplement ces valeurs par défaut, puis modifie les colonnes. Il préserve la nullité et peut gérer les noms contenant des espaces, des tirets, etc. Attention, il ne recrée pas les valeurs par défaut par la suite.

Si vous êtes dans la même situation, vous pouvez utiliser ce script stable et testé, qui garantit également l'absence de troncature silencieuse de la variable nvarchar (max) utilisée pour composer les instructions 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

Il utilise une syntaxe et des tables de schéma anciennes. Il fonctionne donc à partir de SQL Server version 2008 (qui a été le premier à prendre en charge datetime2 ) à 2016.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top