16

In MSSQL habe ich eine Tabelle wie folgt erstellt:Wie ändert man die Länge von Varchar im zusammengesetzten Primärschlüssel?

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

Jetzt möchte ich Spalte die Länge der ‚Daten‘ zu erhöhen, von 255 bis 4000.

Wenn ich versuche einfach:

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

Dann bekomme ich diesen Fehler:

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

Wenn ich das versuchen:

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

Dann bekomme ich diesen Fehler:

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

Was bin ich? Beide Spalten wurden mit NOT NULL definiert. Warum meldet MSSQL, dass diese Einschränkung nicht erneut erstellt werden kann, nachdem ich sie gelöscht habe?

Danke! Evan

+2

Nur ein Wort der Vorsicht - das ist eine wirklich sehr schlechte Wahl für einen primären (und damit standardmäßig Clustering) Index. Der Indexeintrag kann bis zu 259 Bytes groß sein und wird in jeden einzelnen Eintrag jedes nicht gruppierten Indexes auf dieser Tabelle dupliziert, was potentiell dazu führen kann, dass die über Gut und Böse hinausgehen .... Ich würde befürworten, einen Ersatz zu verwenden 'MyTableID INT IDENTITY' in diesem Fall und machen ** das ** Ihren primären/Clustering-Schlüssel. –

Antwort

20

Indem Sie den Datentyp auf varchar(4000) ändern, akzeptieren Sie NULLs.

Versuchen Sie folgendes:

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

Beachten Sie, dass die Indexgröße (die für PK implizit erstellen ist) zu 900 Bytes begrenzt ist und Einsätze von größeren Werten wird scheitern.

+0

Doh. Na sicher. Vielen Dank. Also wirklich das Größte, auf das ich die Länge einstellen kann ist dann 900? –

+2

'@ evan.leonard': eigentlich' 896', da 'fkid'' '4' Bytes zum Speichern benötigt. – Quassnoi

2

Seien Sie nicht überrascht, wenn Sie eine Warnung erhalten, wenn Sie diesen Index am Ende erstellen, geben Sie ihm die Möglichkeit, einen Indexschlüssel größer als die zulässigen 900 Bytes zu erstellen. (Da die PK wird entweder den Clustered-Index (Standard) oder ein NC-Index Strafvollzugs.)

3

Sie müssen die Einschränkung nicht fallen, einfach NOCHECK es

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 

** beachten Sie, dass ist Wenn Sie nur im Sinne von "Erhöhen" arbeiten, funktioniert das nicht, um die Größe zu verringern, da dies zu einer Verletzung der Primärschlüsseleinschränkung führen könnte (denken Sie, wenn Sie zwei Datenzellen AAB und AAC hatten und die Größe um eins verringert haben.) In diesem Fall müssten Sie die Einschränkung löschen, aber nicht bevor Sie eine SQL-Anweisung haben, die die Daten in einer temporären Tabellenüberprüfung speichert, um sicherzustellen, dass sie in Ihre neue geänderte Spalte ohne Überfüllungen passt und dann wieder auf die neue aktualisiert wird geänderte Tabellenspalte

Verwandte Themen