这将列出表中所有可为空的列:
select tab.name, col.name
from sys.columns col join sys.tables tab on col.object_id = tab.object_id
where tab.type = 'U' and col.is_nullable = 1
您可能会使用游标来遍历每个,执行一些动态 SQL 来更新列定义。但是,如果您在每一列中都有不同的数据类型,那可能会变得非常糟糕——它们都一样吗?
或者,您可以更新所有 SP 查询以使用:
ISNULL(fieldname, 0) = 0
从那一侧消除 NULL 问题 - 这将匹配 NULL - 或 - 零。
编辑:
好的,假设您要更新所有 INT、TINYINT、BIGINT 和 BIT 列,这个脚本应该可以做到。使用风险自负!备份数据库并将其还原为副本并在那里进行测试。然后,取消注释 WHERE 子句中的表过滤器以首先在单个表上进行测试。EXEC 会被注释,只有在您对它进行筛选后才能取消注释。
该脚本将执行以下操作:
- 将每个 NULL INT、TINYINT、BIGINT 和 BIT 更新为零(假)
- 将每个 INT、TINYINT、BIGINT 和 BIT 列更改为 NOT NULL
- 将每个 INT、TINYINT、BIGINT 和 BIT 列的默认约束添加为零 (false)。
请注意,如果您在列上已有默认约束,则 3 将失败。如果您不需要默认值(即您为每个 INSERT 显式插入一个值),请将其删除。
DECLARE @table VARCHAR(MAX), @col VARCHAR(MAX), @type VARCHAR(MAX)
DECLARE @q_update VARCHAR(MAX), @q_alter VARCHAR(MAX), @q_default VARCHAR(MAX)
DECLARE c CURSOR FOR
select tab.name, col.name, typ.name
from sys.columns col
join sys.types typ on col.system_type_id = typ.system_type_id
join sys.tables tab on col.object_id = tab.object_id
where tab.type = 'U' and col.is_nullable = 1 and typ.name IN ('int', 'tinyint', 'bigint', 'bit')
--tab.name = 'sometable'
OPEN c
FETCH NEXT FROM c INTO @table, @col, @type
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'UPDATING ' + @table + '.' + @col + ' (' + @type + ')';
SET @q_update = 'UPDATE [' + @table + '] SET [' + @col + '] = 0 WHERE [' + @col + '] IS NULL';
PRINT @q_update;
--EXEC(@q_update);
PRINT '';
SET @q_alter = 'ALTER TABLE [' + @table + '] ALTER COLUMN [' + @col + '] ' + @type + ' NOT NULL';
PRINT @q_alter;
--EXEC(@q_alter);
PRINT '';
SET @q_default = 'ALTER TABLE [' + @table + '] ADD CONSTRAINT ' + @table + '_' + @col + '_DF DEFAULT 0 FOR [' + @col + ']'
PRINT @q_default;
--EXEC(@q_default);
PRINT '----';
FETCH NEXT FROM c INTO @table, @col, @type
END
CLOSE c
DEALLOCATE c
注意:为了清楚起见,我使用了游标。如果您真的不想使用它们,请随意查看@JamesCurtis链接。