2009-09-18 120 views
3

我有一個數據庫充滿了datetime2列而不是需要移動到SQL 2005數據庫。所以,我需要將所有這些datetime2(7)列轉換爲datetime。T-SQL:將datetime2類型的所有列的datatime2轉換爲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' 

我只是不知道該怎麼做休息。

+0

你爲什麼要加入三個表時,可以從INFORMATION_SCHEMA中獲得所有的信息。列? – Kibbee 2009-09-18 20:56:21

+2

@van,@David。您可能想要在sys中檢查列is_nullable。列來驗證ALTER COLUMN中是否需要NOT NULL – 2009-09-18 20:58:07

回答

5

...然後你遍歷你的結果用光標和動態運行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; 
+0

對不起,我真的不知道太多的SQL。可以擴展嗎? – 2009-09-18 20:59:09

+0

在答案中添加了代碼。基本上你需要改變列的類型,對吧?你可以使用ALTER TABLE ... ALTER COLUMN ...語法來完成它。在光標的幫助下,您可以執行您在類循環中找到的所有列。您可以添加Lucasz指出的列可空性檢查,並將NOT NULL添加到語句中。 – van 2009-09-18 21:03:26

+0

修改:添加檢查爲可空性(未測試)。歡呼聲 – van 2009-09-18 21:08:14

2

我知道這個線程是舊的,但我在做同樣的事情,今天只是想奧菲提起我的技術。無論何時我需要執行大量的DDL語句,我都會創建一個生成所需TSQL的TSQL,然後將結果複製到Query窗口並運行它。你不需要像@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

只是最後一次跟進,我將所有的datetime列轉換爲datetime2(7),所以這裏是我使用的SQL: 'select'ALTER TABLE ['+ t.table_name +'] ALTER COLUMN ['+ column_name +'] datetime2(7)' \t +(case is_nullable ='NO'then'NOT'else''end)+來自INFORMATION_SCHEMA.columns的'NULL'c內部連接 \t information_schema.TABLES t on c.TABLE_NAME = t.table_name where data_type ='datetime'and t.TABLE_TYPE ='base table' order by t.table_name' – sisdog 2011-03-31 18:28:01

1

改進上面的回答,以迎合模式

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 ['[email protected]+'].[' + @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

希望我早點見過這個答案,字面意思就是寫完整的相同的SQL(除了我使用本地遊標)。值得注意的是,這個答案也包含了帶有空格/特殊字符的表名和列名,而接受的名字不包含空格/特殊字符 – 2018-01-02 10:59:26

0

需要做這個今天在模式中的所有用戶表,並且不滿足於現有的任何答案。特別是,我的一些日期時間列有默認值,實際上沒有人需要,但阻礙了ALTER TABLE命令。所以我寫了一個腳本,只是刪除這些默認值,然後更改列。它保留了可空性,並且可以處理包含空格,連字符等的名稱。注意,它不會在之後重新創建默認值。

如果你在同樣的情況是,你可以使用這個穩定和測試腳本,也可以確保有是爲nvarchar(最大)的不沉默截斷變量用來組成DDL語句:

DECLARE @sql AS nvarchar(max)=N'' 

--1. "ALTER TABLE [Tablename] DROP CONSTRAINT [DF__Tablename__Colname__Obfuscation]" 
SELECT @sql=CAST('' AS nvarchar(MAX))[email protected] 
    +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))[email protected] 
    +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

相關問題