2010-04-08 4 views
0

J'ai une très grande table, contenant beaucoup, beaucoup de champs de bits. Ces champs de bits ont été initialement configurés comme nullables. Maintenant, nous venons de décider qu'il n'est pas logique de les annuler. la valeur est Oui ou Non, par défaut Non Autrement dit, le schéma devrait passer de:Mise à jour de la nullité des colonnes dans SQL 2008

create table MyTable( 
    ID bigint not null, 
    Name varchar(100) not null, 
    BitField1 bit null, 
    BitField2 bit null, 
    ... 
    BitFieldN bit null 
) 

à

create table MyTable( 
    ID bigint not null, 
    Name varchar(100) not null, 
    BitField1 bit not null, 
    BitField2 bit not null, 
    ... 
    BitFieldN bit not null 
) 

alter table MyTable add constraint DF_BitField1 default 0 for BitField1 
alter table MyTable add constraint DF_BitField2 default 0 for BitField2 
alter table MyTable add constraint DF_BitField3 default 0 for BitField3 

Je viens juste de passer à travers le SQL Management Studio, la mise à jour tous ces champs à non-nullable, valeur par défaut 0. Et devinez quoi - quand j'essaie de le mettre à jour, SQL Mgmt studio recrée en interne la table, puis essaie de réinsérer toutes les données dans la nouvelle table ... y compris les valeurs nulles! Ce qui bien sûr génère une erreur, car il essaie explicitement d'insérer une valeur nulle dans une colonne non nullable. Aaargh!

Il est évident que je pouvais exécuter des instructions N de mise à jour du formulaire:

update MyTable set BitField1 = 0 where BitField1 is null 
update MyTable set BitField2 = 0 where BitField2 is null 

mais comme je l'ai dit, il y a n champs là-bas, et ce qui est plus, ce changement doit se propager vers plusieurs identiques bases de données. Très douloureux à mettre en œuvre manuellement.

Est-il possible de faire en sorte que la modification de la table ignore simplement les valeurs nulles et permette l'activation de la règle par défaut lorsque vous tentez d'insérer une valeur nulle?

Répondre

2

Si vous êtes absolument sûr que vous voulez faire cela pour tous les les colonnes de bits sur la table, vous pouvez utiliser un curseur pour itérer sur ces colonnes et construire le script dynamiquement. Ceci est similaire à la solution d'Alexander, sauf que cela fonctionne si les colonnes ne sont pas numérotées 1..n (ce dont je doute - je suppose que celles-ci ont probablement été simplifiées à des fins d'illustration).

DECLARE @colName sysname; 
DECLARE @sql nvarchar(max); 

DECLARE cur CURSOR LOCAL FAST_FORWARD FOR 
    SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'MyTable' AND DATA_TYPE = 'bit' AND IS_NULLABLE = 'YES'; 

OPEN cur; 

FETCH NEXT FROM cur INTO @colName; 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @sql = N'UPDATE [MyTable] SET ' + QUOTENAME(@colName) 
     + N' = 0 WHERE ' + QUOTENAME(@colName) + N' IS NULL;' 
     + N'ALTER TABLE [MyTable] ALTER COLUMN ' + QUOTENAME(@colName) 
     + N' bit NOT NULL;' 
     + N'ALTER TABLE [MyTable] ADD CONSTRAINT ' + QUOTENAME('DF_' + @colName) 
     + N' DEFAULT(0) FOR ' + QUOTENAME(@colName) + N';'; 

    EXEC (@sql); -- Replace with PRINT @sql; if you want to test first. 

    FETCH NEXT FROM cur INTO @colName; 
END 

CLOSE cur; 
DEALLOCATE cur; 
0

Je pense après tout que je vais juste aller avec les instructions de mise à jour N. C'est un travail unique d'écrire le script, qui consiste principalement à copier-coller, et ensuite je peux exécuter ce script sur toutes les bases de données applicables.

encore, je serais intéressé de savoir s'il y a un autre moyen plus efficace de le faire ...

0
DECLARE @command VARCHAR(8000) 
DECLARE @index int 
SET @index=0 
WHILE @index<=N DO BEGIN 
SET @[email protected]+'update MyTable SET BitField'+cast(@index as varchar(3))+' = 0 WHERE BitField'+cast(@index as varchar(3))+' IS NULL' 
EXEC(@command) 
SET @[email protected]+1 
END 

et ainsi de suite ...

Questions connexes