这有点麻烦,但您可以通过将列添加为可为空、添加约束、决定要为预先存在的行存储什么值、然后使列不为空来做到这一点。我也会回避不受支持的、未记录的存储过程。我发现sp_MSforeachdb 存在问题(这里有一个解决方法),这也可能在这里表现出来。这就是我将如何做到这一点:
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';
SELECT @sql = @sql + CHAR(13) + CHAR(10) + N'ALTER TABLE '
+ QUOTENAME(SCHEMA_NAME([schema_id])) + '.'
+ QUOTENAME(name)
+ ' ADD ChangedBy NVARCHAR(100) NOT NULL;
ALTER TABLE ' + QUOTENAME(SCHEMA_NAME([schema_id])) + '.'
+ QUOTENAME(name) + ' ADD CONSTRAINT DF_' + name
+ '_ChangedBy DEFAULT (SUSER_SNAME()) FOR ChangedBy;
UPDATE ' + QUOTENAME(SCHEMA_NAME([schema_id])) + '.'
+ QUOTENAME(name) + ' SET ChangedBy = N''pre-existing'';
ALTER TABLE ' + QUOTENAME(SCHEMA_NAME([schema_id])) + '.'
+ QUOTENAME(name) + ' ALTER COLUMN ChangedBy NVARCHAR(100) NOT NULL;'
FROM sys.tables WHERE is_ms_shipped = 0;
PRINT @sql;
--EXEC sys.sp_executesql @sql;
(当您相信它正在执行您期望的操作时更改注释。请注意,您可能不会在 PRINT 输出中看到整个命令;根据您拥有的表的数量,它可能会被截断。您可以使用 TOP 1 或一个针对 sys.tables 的附加 WHERE 子句,以查看单个表的命令集是什么样的。)
您也可以在之后简单地重命名约束:
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';
SELECT @sql = @sql + CHAR(13) + CHAR(10)
+ N'EXEC sp_rename N''' + c.name + ''',N''DF_' + t.name
+ '_ChangedBy'', N''OBJECT'';'
FROM sys.default_constraints AS c
INNER JOIN sys.tables AS t
ON c.parent_object_id = t.[object_id]
WHERE c.name LIKE 'DF[_]%[_]Change[_]%'
AND LOWER(c.[definition]) LIKE '%suser%';
PRINT @sql;
--EXEC sys.sp_executesql @sql;
这些脚本都假设您没有愚蠢的对象名称,例如1 of My Friend's Cool High % Table!
.