2009-04-10 13 views
6

Tengo una tabla con clave principal en mi tabla MS SQL Server 2005. Me gustaría deshabilitarlo. Ahora recibo un error:¿Cómo se desactiva la restricción de clave primaria mediante programación?

Violación de la restricción PRIMARY KEY 'PK_Name'. No se puede insertar una clave duplicada en el objeto 'dbo.Table'.

Me gustaría que este error no ocurra y para trabajar con PRIMARY KEY como con la columna normal sin restricción y restaurar esta restricción después de hacer mis cambios. ¿Cómo deshabilitar esta restricción?

Query Deseo ejecutar mientras que la restricción PRIMARY KEY se desactiva y es compleja y cambia los valores en la columna de la clave principal. En algunos puntos de esta consulta, aparece la situación cuando tengo valores duplicados en la columna de clave principal. Pero al final de mi consulta tengo todos los valores únicos.

No sé mucho sobre esta restricción porque no soy diseñador de esta tabla. Tengo su nombre, pero ahora no, si está agrupado, etc. (¿Qué es la configuración de esta columna)?

+0

Cambio de valores de PK: esto suena muy, muy raro! ¿Cómo se pueden cambiar los valores que se supone deben usarse para implementar relaciones entre tablas? ¿Estás seguro de que la solución que estás tratando de elaborar es LA solución a tu problema? –

+0

No tengo ninguna relación en este PK. Sé que suena raro y tal vez sea así, pero esta es LA solución que necesito aplicar en este lugar. –

+1

Si hay duplicados, ya no es una clave principal, ¿por qué volver a agregarla? ¿Ha considerado una clave primaria concatenada que le permitirá mantener la restricción? –

Respuesta

5

Las tablas relacionales sin claves primarias son algo muy malo. Cada fila tiene que ser única de alguna manera. Si ninguna de las claves candidatas se designa como primaria, toda la fila debe ser única.

No estoy seguro de por qué tiene que soltar una restricción de clave principal, pero consideraría hacerlo sin reemplazarlo con una de las otras claves candidatas, es una señal de advertencia que debería investigarse.

+0

Ha señalado por qué esta solución es mala, así que decidí marcar su respuesta como la correcta. Y aún más, he hecho otra pregunta sobre la solución que hará este trabajo de la manera correcta. Creo que: –

+3

Una de las razones por las que es posible que desee eliminar la restricción es si está realizando cambios en la tabla de una gran cantidad de datos. Recientemente agregamos dos columnas nuevas a una tabla con 8 registros Mil. Tomó 23 horas para agregar las columnas. Si eliminamos las restricciones, lleva 12 min. Por supuesto, estamos hablando de actualización sin conexión. Si se trata de una actualización en línea, sería peligroso eliminar las restricciones. – dsum

13
ALTER TABLE mytable DROP CONSTRAINT PK_Name 

Para volver a activarlo:

ALTER TABLE mytable ADD CONSTRAINT PK_Name PRIMARY KEY /* CLUSTERED */ (pk_column) 

Descomentar CLUSTERED si desea que sus PRIMARY KEY ser agrupados (es decir, las filas de la tabla mismos están comprados)

Para averiguar si el PRIMARY KEY está agrupada en no, problema:

EXEC sp_help 'mytable' 

y mira en el conjunto de resultados 6th devuelto.

+0

Esto parece eliminar la restricción.Cómo restaurarlo? –

+0

El problema es que no sé si tengo una clave principal CLUSTERED o no. Entonces no puedo restaurarlo de esta manera. –

+1

La clave principal está agrupada de forma predeterminada, por lo que si no la cambió, se agrupará. –

0

No viole la restricción de PKEY. En mi humilde opinión, es la mejor solución, evitará el costo de reconstruir un PKEY y, ¿qué pasa si no puede (duplicar el restante)?

O

leer el esquema saber cómo reconstruir la restricción PKEY a continuación, utilizar la solución previouly publicado.

+0

Reconstruir PKEY no es un costo para mí, así que me gustaría ir en esta dirección. –

0

Puede ser una mejor idea que SELECT toda su tabla en una tabla temporal, haciendo la transformación sobre la marcha si es posible, y luego copiando de nuevo. Y si no puede transformarse sobre la marcha, es mucho más fácil agregar un índice de fila entera simple como clave principal en la tabla temporal.

2

Para saber cuál es la clave principal (suponiendo que su tabla es dbo.T1):

select si.name as name, 
(case when (si.status & 16) > 0 then 1 else 0 end) as isclust, 
si.keycnt as keycnt, 
si.indid as indid 
from sysindexes si 
left join sysobjects so on so.id = si.id 
where si.indid > 0 
and si.indid < 255 
and so.xtype <> 'S' 
and so.id = OBJECT_ID('dbo.T1') 
and (si.status & 2048) > 0 

Esto le dará algo como:

 
name         isclust  keycnt indid 
--------------------------------------------------------------- 
PK_T1          1   2  1 

Aquí tienen su nombre de la clave primaria (PK_T1), ya sea agrupado o no, el número de campos en el mismo (2) y índice de identificación (lo necesitará más adelante).

A continuación ejecute el siguiente:

select INDEX_COL('dbo.T1', 1, 1) --returns Field1 
select INDEX_COL('dbo.T1', 1, 2) --returns Field2 

Esto le dará los nombres de los dos campos del índice. El primer parámetro es el nombre de su tabla, el segundo es el índice obtenido antes y el tercero un bucle de 1 a keycnt (devuelto en el paso anterior).

Tener esta información debe ser capaz de reconstruir la clave principal de la siguiente manera:

ALTER TABLE dbo.T1 ADD CONSTRAINT PK_T1 PRIMARY KEY CLUSTERED (Field1, Field2) 

Actualización: Esto podría no ser tan exacto como el análisis resultado sp_help mencionó earlier (que se perderá el orden de clasificación y grupo de archivos) , pero es más fácil programáticamente.

0

La continuación trabajó para mí (usted debe ser db_owner para realizar esta acción)

--Declare una variable para obtener los contraints sobre la mesa y asignar a una variable

DECLARE @PK_CONST_NAME AS varchar(100)<br> 
SET @PK_CONST_NAME = (SELECT NAME FROM SYS.KEY_CONSTRAINTS WHERE OBJECT_NAME(PARENT_OBJECT_ID) = '[TABLENAME]') 

- Variables para almacenar las consultas

SET @DropAlterQuery = ''<br> 
SET @RecreateAlterQuery = '' 

- Contruct consulta

SET @DropAlterQuery = CONCAT('ALTER TABLE [TABLENAME] DROP CONSTRAINT ',@PK_CONST_NAME) 

- Ejecutar la consulta construido para Droping los contraints

EXEC(@DropAlterQuery) 

- modifica la columna Tamaño (Ahora esta declaración funciona como se dejan caer contraints)

ALTER TABLE [TABLENAME] 
ALTER COLUMN BATCH_ID VARCHAR(200) NOT NULL 

- Contruct de consultas

SET @RecreateAlterQuery = CONCAT(CONCAT('ALTER TABLE [TABLENAME] ADD CONSTRAINT ',@PK_CONST_NAME), ' PRIMARY KEY (<<PRIMARY KEY COLUMN1>>, <<PRIMARY KEY COLUMN2>>, <<PRIMARY KEY COLUMN2>>... So on)') 

- Ejecutar la consulta construido para recrear el contraints abandonado

EXEC(@RecreateAlterQuery) 
Cuestiones relacionadas