tutoriales tutorial studio management español engine sql-server sql-server-2005

sql-server - tutorial - tsql sql server



Columna de caída de SQL Server 2005 con restricciones (13)

Simplemente genere scripts para la tabla. Ahí puede encontrar el nombre de todas las restricciones.

Tengo una columna con una restricción "DEFAULT". Me gustaría crear un script que elimine esa columna.

El problema es que devuelve este error:

Msg 5074, Level 16, State 1, Line 1 The object ''DF__PeriodSce__IsClo__4BCC3ABA'' is dependent on column ''IsClosed''. Msg 4922, Level 16, State 9, Line 1 ALTER TABLE DROP COLUMN IsClosed failed because one or more objects access this column.

No pude encontrar una manera fácil de descartar una columna y todas sus restricciones asociadas (solo encontré grandes scripts que miran en la tabla del sistema ... DEBE (!) Ser una "buena" manera de hacerlo).

Y como el nombre de la restricción DEFAULT se ha generado aleatoriamente, no puedo soltarlo por su nombre.

Actualización :
El tipo de restricción es "POR DEFECTO".

Vi las soluciones que todos ustedes propusieron, pero las encuentro realmente "sucias" ... ¿No creen? No sé si es con Oracle o MySQL, pero es posible hacer algo como:

DROP COLUMN xxx CASCADE CONSTRAINTS

Y elimina todas las restricciones relacionadas ... O al menos elimina automáticamente las restricciones asignadas a esa columna (¡al menos restricciones de CHECK!)

¿No hay nada como eso en MSSQL?


¿Qué quieres decir al azar generado? Puede buscar las restricciones en la columna específica en Management Studio o a través de la vista sys.tables y buscar cuáles son los nombres.

Luego, puede cambiar su secuencia de comandos para eliminar las restricciones antes de soltar la columna. ¿Qué tipo de restricción es esto? Si se trata de una restricción de clave externa, asegúrese de que hacerlo no perjudicará la integridad de los datos en su base de datos.


Creo que eliminar explícitamente las restricciones antes de eliminar la columna es una solución "limpia". De esta manera, no abandones las restricciones de las que quizás no estés consciente. Si la caída aún falla, usted sabe que quedan restricciones adicionales. Me gusta tener el control de exactamente lo que está sucediendo en mi base de datos.

Además, la creación de scripts de las caídas garantiza explícitamente la secuencia de comandos y, con suerte, los resultados se pueden repetir exactamente de la manera que usted desea.


Puede obtener los nombres de restricciones consultando las vistas del sistema information_schema.

select CONSTRAINT_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_NAME = ''<tablename>'' AND COLUMN_NAME = ''IsClosed''


> select CONSTRAINT_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE > WHERE TABLE_NAME = ''<tablename>'' AND COLUMN_NAME = ''IsClosed''

No es la solución correcta, como se explica aquí: http://msdn.microsoft.com/en-us/library/aa175912.aspx que:

Desafortunadamente, el nombre de la restricción predeterminada de columna no se mantiene en la vista COLUMNAS ANSI, por lo que debe volver a las tablas del sistema para encontrar el nombre

La única forma que encontré para obtener el nombre de la restricción DEFAULT es esta solicitud:

select t_obj.name as TABLE_NAME ,c_obj.name as CONSTRAINT_NAME ,col.name as COLUMN_NAME from sysobjects c_obj join sysobjects t_obj on c_obj.parent_obj = t_obj.id join sysconstraints con on c_obj.id = con.constid join syscolumns col on t_obj.id = col.id and con.colid = col.colid where c_obj.xtype = ''D''

¿Soy el único que se encuentra loco al no poder eliminar fácilmente una restricción que solo afecta a las columnas que intento eliminar?
Necesito ejecutar una solicitud con 3 uniones solo para obtener el nombre ...


Esta consulta encuentra restricciones predeterminadas para una tabla dada. No es bonito, estoy de acuerdo:

select col.name, col.column_id, col.default_object_id, OBJECTPROPERTY(col.default_object_id, N''IsDefaultCnst'') as is_defcnst, dobj.name as def_name from sys.columns col left outer join sys.objects dobj on dobj.object_id = col.default_object_id and dobj.type = ''D'' where col.object_id = object_id(N''dbo.test'') and dobj.name is not null

[EDIT] Actualizado por comentario de Julien N


Tal vez podría ayudar un poco más:

declare @tablename nvarchar(200) declare @colname nvarchar(200) declare @default sysname, @sql nvarchar(max) set @tablename = ''your table'' set @colname = ''column to drop'' select @default = name from sys.default_constraints where parent_object_id = object_id(@tablename) AND type = ''D'' AND parent_column_id = ( select column_id from sys.columns where object_id = object_id(@tablename) and name = @colname ) set @sql = N''alter table '' + @tablename + '' drop constraint '' + @default exec sp_executesql @sql set @sql = N''alter table '' + @tablename + '' drop column '' + @colname exec sp_executesql @sql

Solo es necesario configurar las variables @tablename y @colname para descartar la columna.


También creo que es una falla en el servidor SQL no tener una caída en cascada disponible. Me centré en ello consultando las tablas del sistema de la misma manera que otras personas que se describen aquí:

  • INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE solo enumera claves externas, claves principales y restricciones exclusivas.
  • La única forma de buscar restricciones predeterminadas es buscarlas en sys.default_constraints.
  • Lo que no se ha mencionado aún aquí es que los índices también hacen que falle una columna, por lo que también debe descartar todos los índices que usan su columna antes de continuar con la eliminación de una columna.

El script resultante no es bonito, pero lo puse en un procedimiento almacenado para poder reutilizarlo:

CREATE PROCEDURE DropColumnCascading @tablename nvarchar(500), @columnname nvarchar(500) AS SELECT CONSTRAINT_NAME, ''C'' AS type INTO #dependencies FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_NAME = @tablename AND COLUMN_NAME = @columnname INSERT INTO #dependencies select d.name, ''C'' from sys.default_constraints d join sys.columns c ON c.column_id = d.parent_column_id AND c.object_id = d.parent_object_id join sys.objects o ON o.object_id = d.parent_object_id WHERE o.name = @tablename AND c.name = @columnname INSERT INTO #dependencies SELECT i.name, ''I'' FROM sys.indexes i JOIN sys.index_columns ic ON ic.index_id = i.index_id and ic.object_id=i.object_id JOIN sys.columns c ON c.column_id = ic.column_id and c.object_id=i.object_id JOIN sys.objects o ON o.object_id = i.object_id where o.name = @tableName AND i.type=2 AND c.name = @columnname AND is_unique_constraint = 0 DECLARE @dep_name nvarchar(500) DECLARE @type nchar(1) DECLARE dep_cursor CURSOR FOR SELECT * FROM #dependencies OPEN dep_cursor FETCH NEXT FROM dep_cursor INTO @dep_name, @type; DECLARE @sql nvarchar(max) WHILE @@FETCH_STATUS = 0 BEGIN SET @sql = CASE @type WHEN ''C'' THEN ''ALTER TABLE ['' + @tablename + ''] DROP CONSTRAINT ['' + @dep_name + '']'' WHEN ''I'' THEN ''DROP INDEX ['' + @dep_name + ''] ON dbo.['' + @tablename + '']'' END print @sql EXEC sp_executesql @sql FETCH NEXT FROM dep_cursor INTO @dep_name, @type; END DEALLOCATE dep_cursor DROP TABLE #dependencies SET @sql = ''ALTER TABLE ['' + @tablename + ''] DROP COLUMN ['' + @columnname + '']'' print @sql EXEC sp_executesql @sql


Me encontré con esto. Puede eliminar la columna con restricciones utilizando la vista de diseño MSSQL. Haga clic con el botón derecho en la columna que desea eliminar (con o sin restricciones) y podrá eliminar esto sin ningún problema. Ha ... Ya parecía estúpido.


Buscar el nombre del contraint o usar la vista de diseño de MSSQL no siempre es una opción. Actualmente quiero hacer un script para eliminar una columna con un contraint en él. Usar el nombre no es una opción ya que el nombre se genera y quiero usar el script en diferentes entornos Dev / Sys / Prod / etc. No es posible usar el nombre porque los nombres de los términos diferirán según el entorno. Probablemente tenga que mirar la tabla de sistemas, pero estoy de acuerdo en que debería haber una opción más fácil disponible.


La respuesta de pvolders fue justo lo que necesitaba, pero no detecté las estadísticas que causaban y error. Este es el mismo código, menos la creación de un procedimiento almacenado, además de enumerar las estadísticas y soltarlas. Esto es lo mejor que se me ocurre, así que si hay una forma mejor de determinar qué estadísticas se deben eliminar, agregue.

DECLARE @tablename nvarchar(500), @columnname nvarchar(500) SELECT @tablename = ''tblProject'', @columnname = ''CountyKey'' SELECT CONSTRAINT_NAME, ''C'' AS type INTO #dependencies FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_NAME = @tablename AND COLUMN_NAME = @columnname INSERT INTO #dependencies select d.name, ''C'' from sys.default_constraints d join sys.columns c ON c.column_id = d.parent_column_id AND c.object_id = d.parent_object_id join sys.objects o ON o.object_id = d.parent_object_id WHERE o.name = @tablename AND c.name = @columnname INSERT INTO #dependencies SELECT i.name, ''I'' FROM sys.indexes i JOIN sys.index_columns ic ON ic.index_id = i.index_id and ic.object_id=i.object_id JOIN sys.columns c ON c.column_id = ic.column_id and c.object_id=i.object_id JOIN sys.objects o ON o.object_id = i.object_id where o.name = @tableName AND i.type=2 AND c.name = @columnname AND is_unique_constraint = 0 INSERT INTO #dependencies SELECT s.NAME, ''S'' FROM sys.stats AS s INNER JOIN sys.stats_columns AS sc ON s.object_id = sc.object_id AND s.stats_id = sc.stats_id INNER JOIN sys.columns AS c ON sc.object_id = c.object_id AND c.column_id = sc.column_id WHERE s.object_id = OBJECT_ID(@tableName) AND c.NAME = @columnname AND s.NAME LIKE ''_dta_stat%'' DECLARE @dep_name nvarchar(500) DECLARE @type nchar(1) DECLARE dep_cursor CURSOR FOR SELECT * FROM #dependencies OPEN dep_cursor FETCH NEXT FROM dep_cursor INTO @dep_name, @type; DECLARE @sql nvarchar(max) WHILE @@FETCH_STATUS = 0 BEGIN SET @sql = CASE @type WHEN ''C'' THEN ''ALTER TABLE ['' + @tablename + ''] DROP CONSTRAINT ['' + @dep_name + '']'' WHEN ''I'' THEN ''DROP INDEX ['' + @dep_name + ''] ON dbo.['' + @tablename + '']'' WHEN ''S'' THEN ''DROP STATISTICS ['' + @tablename + ''].['' + @dep_name + '']'' END print @sql EXEC sp_executesql @sql FETCH NEXT FROM dep_cursor INTO @dep_name, @type; END DEALLOCATE dep_cursor DROP TABLE #dependencies SET @sql = ''ALTER TABLE ['' + @tablename + ''] DROP COLUMN ['' + @columnname + '']'' print @sql EXEC sp_executesql @sql


Para basarme en la respuesta de Jeremy Stein, creé un procedimiento almacenado para esto y lo configuré para que se pueda usar para eliminar una columna que tiene o no restricciones predeterminadas. No es muy eficiente, ya que está consultando sys.columns dos veces, pero funciona.

CREATE PROCEDURE [dbo].[RemoveColumnWithDefaultConstraints] -- Add the parameters for the stored procedure here @tableName nvarchar(max), @columnName nvarchar(max) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; DECLARE @ConstraintName nvarchar(200) SELECT @ConstraintName = Name FROM SYS.DEFAULT_CONSTRAINTS WHERE PARENT_OBJECT_ID = OBJECT_ID(@tableName) AND PARENT_COLUMN_ID = (SELECT column_id FROM sys.columns WHERE NAME = (@columnName) AND object_id = OBJECT_ID(@tableName)) IF @ConstraintName IS NOT NULL EXEC(''ALTER TABLE '' + @tableName + '' DROP CONSTRAINT '' + @ConstraintName) IF EXISTS(SELECT * FROM sys.columns WHERE Name = @columnName AND Object_ID = Object_ID(@tableName)) EXEC(''ALTER TABLE '' + @tableName + '' DROP COLUMN '' + @columnName) END GO


Aquí hay una secuencia de comandos que eliminará la columna junto con su restricción predeterminada. Reemplace MYTABLENAME y MYCOLUMNNAME apropiadamente.

declare @constraint_name sysname, @sql nvarchar(max) select @constraint_name = name from sys.default_constraints where parent_object_id = object_id(''MYTABLENAME'') AND type = ''D'' AND parent_column_id = ( select column_id from sys.columns where object_id = object_id(''MYTABLENAME'') and name = ''MYCOLUMNNAME'' ) set @sql = N''alter table MYTABLENAME drop constraint '' + @constraint_name exec sp_executesql @sql alter table MYTABLENAME drop column MYCOLUMNNAME go