1

使用 SQL Server 2008,我创建了一个数据库,其中每个表都有一个名为“CreatedDt”的日期时间列。我想做的是为每个表创建一个触发器,以便在插入值时,用当前日期和时间填充 CreatedDt 列。

如果你能原谅我的伪代码,我所追求的是 T-SQL 等价于:

foreach (Table in MyDatabase)
{
   create trigger CreatedDtTrigger
   {
        on insert createddt = datetime.now;
   }
}

如果有人愿意帮忙,我将不胜感激。谢谢!

4

3 回答 3

2

正如@EricZ 所说,最好的办法是为该列绑定一个默认值。以下是使用游标和动态 SQL 将其添加到每个表的方法:

当然,你可以用光标来做:

declare @table sysname, @cmd nvarchar(max)
declare c cursor for
  select name from sys.tables where is_ms_shipped = 0 order by name
open c; fetch next from c into @table
while @@fetch_status = 0
begin
  set @cmd = 'ALTER TABLE ' + @table + ' ADD CONSTRAINT DF_' + @table + '_CreateDt DEFAULT GETDATE() FOR CreateDt'
  exec sp_executesql @cmd
  fetch next from c into @table
end
close c; deallocate c
于 2013-04-26T16:24:47.563 回答
2

没必要去Cursors。只需复制下面和的结果QueryExecute

select distinct 'ALTER TABLE '+ t.name + 
' ADD CONSTRAINT DF_'+t.name+'_crdt DEFAULT getdate() FOR '+ c.name
from sys.tables t
inner join sys.columns c on t.object_id=c.object_id
where c.name like '%your column name%'
于 2013-04-26T16:29:42.677 回答
1

这是另一种方法:

DECLARE @SQL nvarchar(max);
SELECT @SQL = Coalesce(@SQL + '
', '')
    + 'ALTER TABLE ' + QuoteName(T.TABLE_SCHEMA) + '.' + QuoteName(T.TABLE_NAME)
    + ' ADD CONSTRAINT ' + QuoteName('DF_'
    + CASE WHEN T.TABLE_SCHEMA <> 'dbo' THEN T.Table_Schema + '_' ELSE '' END
    + C.COLUMN_NAME) + ' DEFAULT (GetDate()) FOR ' + QuoteName(C.COLUMN_NAME)
    + ';'
FROM
   INFORMATION_SCHEMA.TABLES T
   INNER JOIN INFORMATION_SCHEMA.COLUMNS C
      ON T.TABLE_SCHEMA = C.TABLE_SCHEMA
      AND T.TABLE_NAME = C.TABLE_NAME
WHERE
   C.COLUMN_NAME = 'CreatedDt'
;
EXEC (@SQL);

这会产生并运行一系列类似于以下的语句:

ALTER TABLE [schema].[TableName] -- (line break added)
   ADD CONSTRAINT [DF_schema_TableName] DEFAULT (GetDate()) FOR [ColumnName];

一些注意事项:

  • 这使用INFORMATION_SCHEMA视图。最好的做法是尽可能使用这些而不是系统表,因为它们保证不会在 SQL Server 的版本之间发生变化(而且许多 DBMS 都支持它们,所以在所有条件相同的情况下,最好使用符合标准/可移植的代码)。

  • 在具有区分大小写的默认排序规则的数据库中,INFORMATION_SCHEMA视图名称和列名称必须使用大写。

  • 创建脚本时,重要的是要注意模式名称和正确的转义(使用QuoteName)。不这样做总有一天会破坏某人的系统。

  • 我认为将DEFAULT表达式放在括号内是最佳做法。虽然在这种情况下没有它不会收到错误,但如果函数GetDate()被参数化和/或曾经更改为更复杂的表达式,则不会有任何错误。

如果您决定列默认值对您不起作用,那么您想象的触发器仍然是可能的。但是需要一些认真的工作来管理触发器是否已经存在并适当地更改或创建它,加入inserted触发器内部的元表,并根据表的主键列的完整列表(如果它们存在,如果他们不这样做,那么你就不走运了)。这很有可能,但极其困难——您最终可能会得到嵌套、嵌套、嵌套的动态 SQL。我有这样的自动化对象创建脚本,它连续包含 13 个引号......

于 2013-04-26T17:18:57.640 回答