我的数据库有很多记录,记录了正在或将要采取的各种行动的日期时间。为了正确测试数据库,我想将所有这些都移到过去,6 个月,一年等(而不是更改系统时间)。我怎样才能通过存储过程实现这一点,按天数参数化?
(如果您还包括其他日期/时间类型,例如 datetime2,则可以加分)
需要明确的是,我正在寻找能够动态更新所有表中所有列的东西。
我的数据库有很多记录,记录了正在或将要采取的各种行动的日期时间。为了正确测试数据库,我想将所有这些都移到过去,6 个月,一年等(而不是更改系统时间)。我怎样才能通过存储过程实现这一点,按天数参数化?
(如果您还包括其他日期/时间类型,例如 datetime2,则可以加分)
需要明确的是,我正在寻找能够动态更新所有表中所有列的东西。
看起来很简单...
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
使用风险自负!这将对整个数据库进行大规模更新!确保手头有足够的备份以防万一出现问题!
这非常简单,因为它假定所有表都在默认模式中 - 我不检查并在此示例中包含模式信息。可以添加 - 只是让事情更复杂/更复杂。