16

En MSSQL tengo una tabla creada de esta manera:¿Cómo alterar la longitud de varchar en la clave primaria compuesta?

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

Ahora quiero aumentar la longitud de la columna '' de datos de 255 a 4000.

Si sólo trato:

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

Entonces me sale este error:

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

Si intento esto:

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

Entonces me sale este error:

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

¿Qué me falta? Ambas columnas se definieron con NOT NULL, entonces, ¿por qué MSSQL informa que no puede volver a crear esta restricción después de descartarla?

Gracias! Evan

+2

Solo una palabra de advertencia: esta es realmente una mala elección para un índice primario (y por lo tanto por clúster predeterminado). La entrada del índice podría tener un tamaño de hasta 259 bytes y se duplicará en todas y cada una de las entradas de todos y cada uno de los índices no agrupados en esa tabla, lo que potencialmente aumentará la diferencia entre el bien y el mal ... Yo recomendaría utilizar un sustituto 'MyTableID INT IDENTITY' en este caso y hacer ** esa ** clave primaria/de clúster. –

Respuesta

20

Al modificar el tipo de datos a varchar(4000), lo hace aceptar NULLs.

Prueba esto:

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

Tenga en cuenta que el tamaño del índice (que se crea implícitamente para PK) se limita a 900 bytes y los insertos de valores mayores fallará.

+0

Doh. Por supuesto. Gracias. ¿Entonces realmente el más grande al que puedo establecerle la longitud es de 900 entonces? –

+2

'@ evan.leonard': en realidad,' 896', ya que 'fkid' requerirá' 4' bytes para almacenar también. – Quassnoi

2

No se sorprenda si aparece una advertencia al crear este índice al final, le está dando la posibilidad de crear una clave de índice mayor que los 900 bytes permitidos. (Desde el PK o bien será el índice agrupado (por defecto) o un índice NC aplicarla.)

3

usted no tiene que quitar la restricción, simplemente NOCHECK que

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 

** en cuenta que es solo va a funcionar en el sentido 'aumentar', no funciona para disminuir el tamaño porque podría causar violaciones de restricción de clave primaria (piense si tenía dos celdas de datos AAB y AAC, y disminuyó el tamaño en uno). en ese caso, tendría que eliminar la restricción, pero no antes de que tenga algunos sql que almacenarán los datos en una tabla de verificación temporal para asegurarse de que encajarán en su nueva columna alterada sin dúplex, y luego actualizarán a la nueva columna de tabla alterada.

Cuestiones relacionadas