T-SQL:将 datetime2 类型的所有列的 datatime2 转换为 datetime

发布于 2024-08-04 23:55:20 字数 424 浏览 7 评论 0原文

我有一个充满 datetime2 列的数据库,需要将其移至 SQL 2005 数据库。因此,我需要将所有这些 datetime2(7) 列转换为日期时间。

我该怎么做呢?

现在,我已经设法为具有 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'

我只是不知道如何执行其余操作。

I've got a database full of datetime2 columns than needs to be moved to a SQL 2005 database. So, I need to convert all these datetime2(7) columns to datetime.

How can I go about doing this?

Right now I've managed to select the table name and column name for all columns with the datetime2 datatype like this:

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'

I just don't know how to do the rest.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

余生共白头 2024-08-11 23:55:20

...然后您使用 CURSOR 迭代您的结果并动态运行 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;

... then you iterate over your results with the CURSOR and dynamically run the DDL like:

ALTER TABLE myTable ALTER COLUMN myColumn datetime [NOT] NULL

so that you get something similar to this (not tested):

Edit: added null-ability check as well:

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;
夜吻♂芭芘 2024-08-11 23:55:20

改进了上面的答案以适应模式

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;

Improved the above answer to cater for schemas

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;
睫毛溺水了 2024-08-11 23:55:20

我知道这个帖子已经很旧了,但我今天也在做同样的事情,只是想提供我的技术。每当我需要执行大量 DDL 语句时,我都会创建一个 TSQL 来生成所需的 TSQL,然后将结果复制到查询窗口中并运行它。您不需要像@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 中使用“结果到文本”选项而不是“结果到网格”选项运行查询。

I know this thread is old but I'm doing the same thing today and just wanted to offer up my technique. Whenever I need to do a lot of DDL statements I create one TSQL that generates the TSQL that's needed and then just copy the results into the Query window and run it. You don't need to write all the cursor code like @van suggestion (although that works fine).

So, for your situation, just run the sql statement:

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

Then, copy the results into a new query window and run it. Sometimes you need to add "GO" statements on their own line between commands. If so, add char(13) + 'GO' into your output string.

Also, make sure to run the query in SQL Mgmt Studio with the "Results to Text" option instead of the "Results to Grid" option.

败给现实 2024-08-11 23:55:20

今天需要对架构中的所有用户表执行此操作,并且对任何现有答案都不满意。特别是,我的一些日期时间列有默认值,实际上没有人需要,但阻碍了 ALTER TABLE 命令。因此,我编写了一个脚本,仅删除这些默认值,然后更改列。它保留可为空性,并且可以处理包含空格、连字符等的名称。注意,它不会在之后重新创建默认值。

如果您遇到同样的情况,您可以使用这个稳定且经过测试的脚本,它还确保用于组成 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

它使用古老的语法和模式表,因此它从 SQL Server 2008 版(这是第一个支持 datetime2)到 2016 年一直有效。

Needed to do this today for all user tables in a schema, and was not satisfied with any of the existing answers. Especially, some of my datetime columns had defaults, which actually nobody needed, but hindered ALTER TABLE commands. So I wrote a script that just drops those defaults, and then changes the columns. It preserves nullability, and can handle names containing spaces, hyphens etc. Caution, it does not recreate the defaults afterwards.

If you're in the same situation, you can use this stable and tested script, which also makes sure that there is no silent truncation of the nvarchar(max) variable used to compose the DDL statements:

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

It uses ancient syntax and schema tables, so it is working from SQL Server version 2008 (which was the first to support datetime2) thru 2016.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文