Как изменить длину 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 сообщает, что он не может воссоздать это ограничение после его удаления?
Спасибо!
Эван
Ответы
Ответ 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, обеспечивающим его соблюдение.)