这是另一种方法:
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 个引号......