0

我的数据库有很多记录,记录了正在或将要采取的各种行动的日期时间。为了正确测试数据库,我想将所有这些都移到过去,6 个月,一年等(而不是更改系统时间)。我怎样才能通过存储过程实现这一点,按天数参数化?

(如果您还包括其他日期/时间类型,例如 datetime2,则可以加分)

需要明确的是,我正在寻找能够动态更新所有表中所有列的东西。

4

1 回答 1

7

看起来很简单...

CREATE PROCEDURE dbo.MoveDatesBack @NumberOfDays INT
AS BEGIN

   UPDATE dbo.YourTableNameHere
   SET SomeDateColum = DATEADD(DAY, @NumberOfDays, SomeDateColumn) 

   -- repeat the above statement for each table/column that you need to "move back"

END

像这样调用它:

EXEC  dbo.MoveDatesBack @NumberOfDays = -30

或任何你需要的...

DATEADD函数应适用于 SQL Server 2008 或更高版本中的任何日期类型 - 如果将其应用于 a DATETIME2,您将获得一个新的DATETIME2

但这对于 Stackoverflow 来说似乎太简单了——我在这里错过了什么?

更新:如果您想在整个数据库中的所有表和所有与日期相关的列中全局执行此操作 - 您可以使用基于游标的方法,如下所示:

CREATE PROCEDURE dbo.MoveDatesBack @NumberOfDays INT
AS BEGIN
  DECLARE TableCursor CURSOR FAST_FORWARD 
  FOR
     SELECT t.Name, c.name
     FROM sys.columns c 
     INNER JOIN sys.tables t ON c.object_id = t.object_id
     INNER JOIN sys.types typ ON c.system_type_id = typ.system_type_id
     WHERE typ.system_type_id IN (40, 42, 43, 61)  
     -- 40 = date, 42 = datetime2, 43 = datetimeoffset, 61 = datetime

  DECLARE @TableName sysname, @ColumnName sysname

  OPEN TableCursor

  FETCH NEXT FROM TableCursor INTO @TableName, @ColumnName

  WHILE @@FETCH_STATUS = 0
  BEGIN
      DECLARE @Stmt NVARCHAR(999)

      SET @Stmt = 'UPDATE ' + QUOTENAME(@TableName) + 
                  ' SET ' + QUOTENAME(@ColumnName) + ' = DATEADD(DAY, ' + 
                  CAST(@NumberOfDays AS VARCHAR(10)) + ', ' + 
                  QUOTENAME(@ColumnName) + ')'

      -- PRINT @Stmt
      EXEC (@Stmt)

      FETCH NEXT FROM TableCursor INTO @TableName, @ColumnName
  END

  CLOSE TableCursor
  DEALLOCATE TableCursor
END

使用风险自负!这将对整个数据库进行大规模更新!确保手头有足够的备份以防万一出现问题!

这非常简单,因为它假定所有表都在默认模式中 - 我不检查并在此示例中包含模式信息。可以添加 - 只是让事情更复杂/更复杂。

于 2012-11-15T14:18:18.090 回答