关于tsql:SQL Server编程 – 按给定天数更新所有日期

SQL Server programming - update all dates by a given number of days

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

我写了一个脚本(艰难的方法 - 见下文),将每个表中的日期字段增加给定的天数。我们的想法是通过将所有日期更新相同的天数来使数据看起来更"正常"。

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

任何接受者?

谢谢。

示例脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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!

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

DECLARE @numDaysToAdd int

SET @numDaysToAdd = 1

如果@numDaysToAdd> 0

开始

DECLARE @tablename varchar(100)

DECLARE @currtable varchar(100)

DECLARE @currcolumn varchar(100)

DECLARE @columnname varchar(100)

DECLARE @strSQL nvarchar(4000)

DECLARE 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'或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)

1
2
3
4
5
6
BEGIN    

  IF @currcolumn <> @columnname

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

其他

1
2
3
4
5
6
7
8
9
10
11
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

结束

- 运行最后的声明
EXEC sp_executesql @strSQL

关闭tnames_cursor

DEALLOCATE tnames_cursor

结束


你的理解是正确的。听起来你丢失的部分是:

  • 如何查找元数据(什么表
    你有,什么列)
  • 如何建立SQL来走过去
    表格。
  • 对于#1,请参阅系统视图INFORMATION_SCHEMA.TABLESINFORMATION_SCHEMA.COLUMNS

    1
    2
    3
    4
    -- 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执行它。


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

    1
    2
    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

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

    干杯


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