Подтвердить что ты не робот

Как изменить длину varchar в составном первичном ключе?

В MSSQL у меня есть таблица, созданная следующим образом:

CREATE TABLE [mytable] (fkid int NOT NULL, data varchar(255) CONSTRAINT DF_mytable_data DEFAULT '' NOT NULL);
ALTER TABLE [mytable] ADD CONSTRAINT PK_mytable_data PRIMARY KEY (fkid, data);

Теперь я хочу увеличить длину столбца данных с 255 до 4000.

Если я просто попробую:

ALTER TABLE [mytable] ALTER COLUMN data varchar(4000);

Затем я получаю эту ошибку:

The object 'PK_mytable_data' is dependent on the column 'data'

Если я попробую это:

ALTER TABLE [mytable] DROP CONSTRAINT PK_mytable_data;
ALTER TABLE [mytable] ALTER COLUMN data varchar(4000);
ALTER TABLE [mytable] ADD CONSTRAINT PK_mytable_data PRIMARY KEY (fkid, data);

Затем я получаю эту ошибку:

Cannot define PRIMARY KEY constraint on nullable column in table 'mytable'

Что мне не хватает? Оба столбца были определены с NOT NULL, поэтому почему MSSQL сообщает, что он не может воссоздать это ограничение после его удаления?

Спасибо! Эван

4b9b3361

Ответ 1

Изменив тип данных на varchar(4000), вы можете принять его NULLs.

Попробуйте следующее:

ALTER TABLE [mytable] DROP CONSTRAINT PK_mytable_data;
ALTER TABLE [mytable] ALTER COLUMN data varchar(4000) NOT NULL;
ALTER TABLE [mytable] ADD CONSTRAINT PK_mytable_data PRIMARY KEY (fkid, data);

Обратите внимание, что размер индекса (который неявно создается для PK) ограничен 900 байтами, а вставки больших значений не будут выполняться.

Ответ 2

вам не нужно отбрасывать ограничение, просто NOCHECK it

IF EXISTS 
(SELECT 1 FROM sys.tables tab INNER JOIN sys.columns col ON tab.object_id = col.object_id      WHERE tab.name = 'MY_TABLE' AND col.name = 'MY_COLUMN')

BEGIN

ALTER TABLE MY_TABLE NOCHECK CONSTRAINT ALL
ALTER TABLE [dbo].[MY_TABLE] ALTER COLUMN [MY_COLUMN] VARCHAR(50) NOT NULL;
ALTER TABLE MY_TABLE CHECK CONSTRAINT ALL

END

GO

** обратите внимание, что он будет работать только в смысле "увеличения", он не работает для уменьшения размера, поскольку это может привести к нарушениям ограничения первичного ключа (подумайте, были ли у вас две ячейки данных AAB и AAC, а вы уменьшил размер на единицу.) В этом случае вам придется отказаться от ограничения, но не раньше, чем у вас будет какой-то sql, который будет хранить данные в таблице temp check, чтобы убедиться, что он будет соответствовать вашему новому измененному столбцу без дубликатов, а затем обновиться до нового измененного столбца таблицы.

Ответ 3

Не удивляйтесь, если вы получите предупреждение при создании этого индекса в конце, вы даете ему возможность создать индексный ключ, превышающий допустимые 900 байт. (Поскольку PK будет либо кластеризованным индексом (по умолчанию), либо индексом NC, обеспечивающим его соблюдение.)