Обновление обнуляемости столбцов в SQL 2008 - PullRequest
0 голосов
/ 08 апреля 2010

У меня очень широкая таблица, содержащая множество битовых полей. Эти битовые поля были изначально установлены как обнуляемые. Теперь мы только что решили, что не имеет смысла их обнулять; значение равно либо Да, либо Нет, значение по умолчанию. Другими словами, схема должна измениться с:

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

Итак, я только что прошел через SQL Management Studio, обновив все эти поля до значения, отличного от NULL, по умолчанию 0. И угадайте, что - когда я пытаюсь обновить его, SQL Mgmt studio внутренне воссоздает таблицу и затем пытается заново вставить все данные в новую таблицу ... включая нулевые значения! Что, конечно, приводит к ошибке, потому что он явно пытается вставить нулевое значение в необнуляемый столбец. Aaargh!

Очевидно, я мог запустить N операторов обновления вида:

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

но, как я уже говорил, есть поля n , и, более того, это изменение должно распространиться на несколько идентичных баз данных. Очень больно осуществлять вручную.

Есть ли способ заставить модификацию таблицы просто игнорировать нулевые значения и позволить правилу по умолчанию срабатывать при попытке вставить нулевое значение?

Ответы [ 3 ]

2 голосов
/ 08 апреля 2010

Если вы абсолютно уверены, что хотите сделать это для всех битовых столбцов в таблице, вы можете использовать курсор для перебора этих столбцов и динамического построения сценария. Это похоже на решение Александра, за исключением того, что оно работает, если столбцы не нумеруются 1..n (в чем я сомневаюсь - полагаю, что они, вероятно, были упрощены в целях иллюстрации).

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 голосов
/ 08 апреля 2010
DECLARE @command VARCHAR(8000)
DECLARE @index int
SET @index=0
WHILE @index<=N DO BEGIN
 SET @command=@command+'update MyTable SET BitField'+cast(@index as varchar(3))+' = 0 WHERE BitField'+cast(@index as varchar(3))+' IS NULL'
 EXEC(@command)
 SET @index=@index+1
END

и так далее ...

0 голосов
/ 08 апреля 2010

Я думаю, в конце концов, я просто собираюсь пойти с N операторов обновления. Написание сценария, который в основном копируется и вставляется, является разовой работой, и затем я могу запустить этот сценарий для всех применимых баз данных.

Тем не менее, мне было бы интересно узнать, есть ли другой более эффективный способ сделать это ...

...