SQL Server 2005/2008中是否有任何方法可以将列重置为其默认值?

时间:2012-10-08 16:14:40

标签: sql sql-server stored-procedures

有些人使用我们的软件已经完成了数据库服务器移动,而不是遵循我们正常的步骤,这些步骤适用于所有数据库中我们软件的遗留部分nulls = 0。因此,由于他们忽略了使用我们的协议,我们留下了大量的垃圾空数据和许多fieldname = 0的查询失败,因为fieldname is null是真的。

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

我几乎没有使用存储过程的经验,并且在存储过程中几乎没有Oracle DB之外的经验,所以如果您可以使用代码示例回答这个问题并且如果无法在多个表上运行过程,请解释代码正在执行的操作,我也很高兴知道,在这种情况下,我只会编写一个实用程序(尽管我已经看到该实用程序需要9年才能运行)

3 个答案:

答案 0 :(得分:3)

您的标题说将字段设置为null但您的问题表明应该没有空值。尽管如此....您可以使用DEFAULT关键字将字段设置为默认值:

Update MyTable set MyField = DEFAULT Where <something>

答案 1 :(得分: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 -or-Zero。

编辑:

好的,假设您要更新所有INT,TINYINT,BIGINT和BIT列,此脚本 应该 执行此操作。尽管使用风险自负!备份数据库并将其还原为副本并在那里进行测试。然后,取消注释WHERE子句中的表过滤器以首先测试单个表。 EXEC被评论,只有在您将其测试到屏幕后才会取消注释。

此脚本将执行以下操作:

  1. 将每个NULL INT,TINYINT,BIGINT和BIT更新为零(false)
  2. 将每个INT,TINYINT,BIGINT和BIT列更改为NOT NULL
  3. 将每个INT,TINYINT,BIGINT和BIT列的默认约束添加到零(false)。
  4. 请注意,如果列上已有默认约束,则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 link

答案 2 :(得分: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);