T-SQL:datetime2型のすべての列のdatatime2をdatetimeに変換します
質問
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'
残りの操作方法がわかりません。
解決
...その後、CURSORを使用して結果を反復処理し、次のようにDDLを動的に実行します。
ALTER TABLE myTable ALTER COLUMN myColumn datetime [NOT] NULL
これに似たものが得られるように(テストされていません):
編集: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を1つ作成し、結果をクエリウィンドウにコピーして実行します。 @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コマンドを妨害しました。そこで、これらの既定値を削除してから列を変更するだけのスクリプトを作成しました。 null可能性を保持し、スペース、ハイフンなどを含む名前を処理できます。注意、デフォルトを後で再作成しません。
同じ状況にある場合は、この安定したテスト済みのスクリプトを使用できます。これにより、DDLステートメントの構成に使用されるnvarchar(max)変数のサイレントトランケーションがないことも確認できます。
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
古代の構文テーブルとスキーマテーブルを使用しているため、2016年まではSQL Serverバージョン2008( datetime2
をサポートした最初のバージョン)から動作しています。