web-dev-qa-db-ja.com

複合主キーの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'

何が足りないのですか?両方の列がNOTNULLで定義されているのに、MSSQLが、この制約を削除した後、この制約を再作成できないと報告するのはなぜですか?

ありがとう!エヴァン

16
evan.leonard

データ型を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バイトに制限されており、それより大きい値の挿入は失敗することに注意してください。

20
Quassnoi

制約を削除する必要はありません。単にNOCHECKしてください。

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のセルが2つあり、サイズを縮小した場合を考えてみてください)。その場合、制約を削除する必要がありますが、データを一時テーブルに格納するSQLを取得する前に、データが重複なしで新しい変更された列に収まるかどうかを確認してから、新しく変更されたテーブル列に更新し直します。

3
jason malley

最後にこのインデックスを作成するときに警告が表示されても驚かないでください。許可されている900バイトを超えるインデックスキーを作成する可能性があります。 (PKはクラスター化インデックス(デフォルト)またはそれを強制するNCインデックスのいずれかになるためです。)

2
Andrew