代码之家  ›  专栏  ›  技术社区  ›  jo

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

  •  2
  • jo  · 技术社区  · 15 年前

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

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

    我确信有一种更简单的方法可以做到这一点:循环系统表以标识数据库中的每个用户表,禁用其中的所有触发器,通过向每个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

    设置@numdaystoadd=1

    如果@numdaystoadd>0

    开始

    声明@tablename varchar(100)

    声明@currtable varchar(100)

    声明@currcolumn varchar(100)

    声明@columnname varchar(100)

    声明@strsql nvarchar(4000)

    声明名称光标

    为了

    选择t.table_name,c.column_name

    从information_schema.columns c join information_schema.tables t on t.table_name=c.table_name

    其中(c.data_type='smalldatetime'或c.data_type='datetime')和t.table_type<gt;'view'

    按t.table_name,c.column_name desc排序

    打开名称光标

    从tnames_cursor提取next到@tablename,@columnname

    设置@currcolumn=@columnname

    set@currtable=@tablename

    set@strsql=n'update'+@tablename+char(13)+char(10)+'set'+@columnname+'=dateadd(day,'+convert(varchar(10),@numdaystoadd)+','+@columnname+')'

    同时(@@fetch\u 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
    

    从tnames_cursor提取next到@tablename,@columnname

    结束

    --运行最终语句 exec sp_executesql@strsql

    关闭名称光标

    取消分配名称光标

    结束

    3 回复  |  直到 15 年前
        1
  •  1
  •   Michael Petrotta user3140870    15 年前

    你的理解是正确的。听起来你丢失的东西是:

    1. 如何查找元数据(哪些表 你有,还有什么专栏)
    2. 如何构建SQL来遍历 桌子。

    有关1,请参见系统视图 INFORMATION_SCHEMA.TABLES INFORMATION_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
  •  0
  •   Cody C    15 年前

    我同意。另一个选项是使用系统表为所有200个表生成SQL。然后可以使用sp_execsql执行。不会更改执行,但会保存您键入的内容,这是非常重要的:)

        3
  •  0
  •   Arnkrishn    15 年前

    下面的查询将为您提供“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是数据类型-smalldatetime的系统类型\u id。您可以从sys.types表中验证它。

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

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

    干杯

    推荐文章