1

一些使用我们软件的人已经开始进行数据库服务器移动,而不是按照我们的正常步骤来容纳我们软件nulls = 0在所有数据库中的遗留部分。因此,由于他们忽略了使用我们的协议,所以我们留下了很多垃圾空数据,并且很多查询fieldname = 0都失败了,因为fieldname is null它是真的。

那么,如何构建一个存储过程以将所有空值(实际上不应该有空值)恢复为 SQL Server 数据库中的默认值?

我几乎没有执行存储过程的经验,并且在存储过程中绝对没有 Oracle DB 之外的经验,所以请解释一下代码在做什么,如果你可以用代码示例回答这个问题,并且如果不可能在多个表上运行过程,那很好也知道,在这种情况下,我只需编写一个实用程序来完成它(尽管我已经看到该实用程序需要 9 年才能运行)

4

3 回答 3

3

您的标题说将字段设置为空,但您的问题说不应该有空值。不过....您可以使用 DEFAULT 关键字将字段设置为其默认值:

Update MyTable set MyField = DEFAULT Where <something>
于 2012-10-08T16:29:01.643 回答
3

这将列出表中所有可为空的列:

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 会被注释,只有在您对它进行筛选后才能取消注释。

该脚本将执行以下操作:

  1. 将每个 NULL INT、TINYINT、BIGINT 和 BIT 更新为零(假)
  2. 将每个 INT、TINYINT、BIGINT 和 BIT 列更改为 NOT NULL
  3. 将每个 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链接。

于 2012-10-08T16:35:46.117 回答
1

这是一个可以完成您需要的代码示例。

大量免责声明。此代码会将具有默认值的每个可空列重置为其默认。你几乎肯定会想要限制它的范围。

-- Routine which finds all NULLABLE columns with default values
-- and sets them back to their defaults.

-- DISCLAIMER.  If in any doubt, comment the EXEC out and copy and paste
-- the contents of @sql into a query window, and inspect before running.

-- Soon to hold executable SQL
DECLARE @sql VARCHAR(Max)

-- Use the INFORMATION_SCHEMA to find all qualifying columns, building
-- up a string consisting of a series of simple update statements
--
-- Warning:  My definition of qualifying may differ from yours.
-- Check your WHERE clause. 
--
-- Doity concatenatin' ahoy, Captain!
SELECT
    @sql = 
    CASE WHEN
        @sql IS NULL
    THEN
        'UPDATE ' + TABLE_NAME + ' SET ' + COLUMN_NAME + ' = DEFAULT;'  
    ELSE 
        @sql + 'UPDATE ' + TABLE_NAME + ' SET ' + COLUMN_NAME + ' = DEFAULT;'   
    END
FROM
    INFORMATION_SCHEMA.COLUMNS
WHERE 
    COLUMN_DEFAULT IS NOT NULL
AND IS_NULLABLE = 'YES'
--  Add extra conditions for granularity!!!!

-- Execute sql
EXEC (@sql);
于 2012-10-08T17:01:26.607 回答