SQL Server 编程 - 按给定天数更新所有日期

Posted

技术标签:

【中文标题】SQL Server 编程 - 按给定天数更新所有日期【英文标题】:SQL Server programming - update all dates by a given number of days 【发布时间】:2009-07-02 19:53:55 【问题描述】:

我有一个演示数据库,里面有几百个表。每个表通常至少有一个名为 tstamp 的字段,它是一种 smalldatetime 数据类型。有些表也有其他日期字段。许多表也有 1 个或多个触发器。

我编写了一个脚本(困难的方法 - 见下文)将每个表中的日期字段增加给定的天数。这个想法是通过将所有日期更新相同的天数来使数据看起来更“最新”。

我确信有一种更简单的方法可以做到这一点,方法是遍历系统表以识别数据库中的每个用户表,禁用其上的所有触发器,通过添加天数来修改每个 smalldatetime 字段,重新启用触发器并移动到下一个表。我只是不知道如何编写这样的 T-SQL。

有接受者吗?

谢谢。 乔

示例脚本:

DECLARE @numDaysToAdd int

SET @numDaysToAdd = 100

ALTER TABLE someTableDISABLE TRIGGER someTrigger

UPDATE someTable
SET tstamp = DATEADD(day, @numDaysToAdd, tstamp)

-- update any other smalldatetime field in the table too.

ALTER TABLE someTable ENABLE TRIGGER someTrigger

-- same pattern for 200 more tables!

================================================ ============================================ 省略触发问题,这是一个有效的脚本:

声明@numDaysToAdd int

SET @numDaysToAdd = 1

如果@numDaysToAdd > 0

开始

声明@tablename varchar(100)

声明@currtable varchar(100)

声明@currcolumn varchar(100)

声明@columnname varchar(100)

声明@strSQL nvarchar(4000)

声明 tnames_cursor CURSOR

为了

选择 t.TABLE_NAME,c.COLUMN_NAME

FROM INFORMATION_SCHEMA.COLUMNS c 加入 INFORMATION_SCHEMA.TABLES t ON t.TABLE_NAME = c.TABLE_NAME

WHERE (c.DATA_TYPE = 'smalldatetime' OR c.DATA_TYPE = 'datetime') AND t.TABLE_TYPE'VIEW'

按 t.TABLE_NAME、c.COLUMN_NAME DESC 排序

打开 tnames_cursor

FETCH NEXT FROM tnames_cursor INTO @tablename, @columnname

SET @currcolumn = @columnname

SET @currtable = @tablename

SET @strSQL = N'UPDATE ' + @tablename + CHAR(13)+CHAR(10) + 'SET ' + @columnname + ' = DATEADD(day, ' + CONVERT(varchar(10),@numDaysToAdd) + ', ' + @columnname + ')'

WHILE (@@FETCH_STATUS = 0)

开始

IF (@currtable = @tablename)

BEGIN     

  IF @currcolumn <> @columnname

    SET @strSQL = @strSQL + N',' + CHAR(13)+CHAR(10) + @columnname + ' = DATEADD(day, ' + CONVERT(varchar(10),@numDaysToAdd) + ', ' + @columnname + ')'
END

否则

BEGIN    

  SET @currtable = @tablename

  SET @currcolumn = @columnname

  EXEC sp_executesql @strSQL

  SET @strSQL = N'UPDATE ' + @tablename + CHAR(13)+CHAR(10) + 'SET ' + @columnname + ' = DATEADD(day, ' + CONVERT(varchar(10),@numDaysToAdd) + ', ' + @columnname + ')' 

END

FETCH NEXT FROM tnames_cursor INTO @tablename, @columnname

结束

--运行最后的语句 执行 sp_executesql @strSQL

关闭 tnames_cursor

DEALLOCATE tnames_cursor

结束

【问题讨论】:

【参考方案1】:

你的理解是正确的。听起来您缺少的部分是:

    如何查找元数据(哪些表 你有什么列) 如何构建 SQL 来遍历 桌子。

对于#1,请参阅系统视图INFORMATION_SCHEMA.TABLESINFORMATION_SCHEMA.COLUMNS

-- add your own additional criteria
select t.TABLE_NAME, c.COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS c
join INFORMATION_SCHEMA.TABLES t ON t.TABLE_NAME = c.TABLE_NAME
WHERE c.DATA_TYPE = 'datetime'

对于 #2,您可以将 SQL 语句构建为字符串,遍历您感兴趣的表,然后使用 sp_executesql 执行它。

【讨论】:

【参考方案2】:

我同意。另一种选择是使用系统表为所有 200 个表生成 sql。然后您可以使用 sp_execsql 来执行。不会改变执行,但会节省你的打字时间,这总是很重要的:)

【讨论】:

【参考方案3】:

以下查询将为您提供类型为“smallDateTime”的用户表及其列的列表。

SELECT sys.columns.name as tableName, sys.tables.name as columnName from sys.columns,sys.tables 
where sys.columns.object_id=sys.tables.object_id and sys.columns.system_type_id=58 order by tableName

这里 58 是数据类型的 system_type_id - smallDateTime。您可以从 sys.types 表中进行验证。

您可以使用游标遍历结果集以获取每个表,然后禁用该表上的触发器。检查此触发器禁用/启用http://msdn.microsoft.com/en-us/library/ms189748.aspx

然后继续更新与每个表相关的结果集中的每一列,然后启用触发器。

干杯

【讨论】:

以上是关于SQL Server 编程 - 按给定天数更新所有日期的主要内容,如果未能解决你的问题,请参考以下文章

Sql Server代理作业

SQL Server 获取月份的具体天数

SQL Server 从当前日期计算天数,不包括另一个表中的天数

在 SQL SERVER 中使用交叉应用进行更新

SQL 查询以了解商品销售的后续天数

SQL SERVER:获取两个日期之间的总天数