Как изменить длину varchar в составном первичном ключе? - PullRequest
16 голосов
/ 11 января 2010

В 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);

Теперь я хочу увеличить длину столбца 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 сообщает, что не может воссоздать это ограничение после того, как я его отбросил?

Спасибо! Evan

Ответы [ 3 ]

20 голосов
/ 11 января 2010

Изменяя тип данных на 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 байтами, и вставка больших значений завершится неудачей.

3 голосов
/ 22 августа 2013

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

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, который будет хранить данные в проверке временной таблицы, чтобы убедиться, что она уместится в вашем новом измененном столбце без дублирования и затем обновите обратно до нового измененного столбца таблицы.

2 голосов
/ 11 января 2010

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

...