¿Cómo eliminar la restricción predeterminada de SQL sin saber su nombre?

196

En Microsoft SQL Server, conozco la consulta para verificar si existe una restricción predeterminada para una columna y descartar una restricción predeterminada es:

IF EXISTS(SELECT * FROM sysconstraints
  WHERE id=OBJECT_ID('SomeTable')
  AND COL_NAME(id,colid)='ColName'
  AND OBJECTPROPERTY(constid, 'IsDefaultCnst')=1)    
ALTER TABLE SomeTable DROP CONSTRAINT DF_SomeTable_ColName

Pero debido al error tipográfico en versiones anteriores de la base de datos, el nombre de la restricción podría ser DF_SomeTable_ColNameo DF_SmoeTable_ColName.

¿Cómo puedo eliminar la restricción predeterminada sin ningún error de SQL? Los nombres de restricción predeterminados no aparecen en la tabla INFORMATION_SCHEMA, lo que hace las cosas un poco más complicadas.

Entonces, algo como 'eliminar la restricción predeterminada en esta tabla / columna' o 'eliminar DF_SmoeTable_ColName', pero no dé ningún error si no puede encontrarlo.

Robo
fuente
1
No soy competente con SQL Server, ¿puede cambiar el nombre de una restricción después de descubrir su nombre? "Alterar la tabla para cambiar la restricción de cambio de nombre xxx a yyy" en Oracle.
Juergen Hartelt

Respuestas:

262

Ampliando el código de Mitch Wheat, el siguiente script generará el comando para eliminar la restricción y ejecutarla dinámicamente.

declare @schema_name nvarchar(256)
declare @table_name nvarchar(256)
declare @col_name nvarchar(256)
declare @Command  nvarchar(1000)

set @schema_name = N'MySchema'
set @table_name = N'Department'
set @col_name = N'ModifiedDate'

select @Command = 'ALTER TABLE ' + @schema_name + '.[' + @table_name + '] DROP CONSTRAINT ' + d.name
 from sys.tables t
  join sys.default_constraints d on d.parent_object_id = t.object_id
  join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id
 where t.name = @table_name
  and t.schema_id = schema_id(@schema_name)
  and c.name = @col_name

--print @Command

execute (@Command)
Philip Kelley
fuente
1
Visite stackoverflow.com/a/15786313/2049986 para ver una versión para descartar todas las restricciones para una mesa
Jacob van Lingen
Yo uso sys.check_constraints , no sys.default_constraints
Kiquenet
No es válido si secrearonalgunas columnas que tenían múltiples restricciones predeterminadas o restricciones de verificación , solo se ejecutó para las últimas restricciones en la consulta.
Kiquenet
44
Esta consulta solo aborda las restricciones predeterminadas, de las cuales solo puede haber una por columna. Lidiar con las restricciones de verificación es un problema diferente.
Philip Kelley
1
He actualizado esta respuesta para agregar soporte para nombres de esquema no predeterminados. Espero que no te importe, puedo revertir y publicar una respuesta por separado si lo deseas.
Jakub Januszkiewicz
234

La publicación de blog de Rob Farley podría ser de ayuda:

Algo como:

 declare @table_name nvarchar(256)
 declare @col_name nvarchar(256)
 set @table_name = N'Department'
 set @col_name = N'ModifiedDate'

 select t.name, c.name, d.name, d.definition
 from 
     sys.tables t
     join sys.default_constraints d on d.parent_object_id = t.object_id
     join sys.columns c on c.object_id = t.object_id
                           and c.column_id = d.parent_column_id
 where 
     t.name = @table_name
     and c.name = @col_name
Trigo Mitch
fuente
104

Descubrí que esto funciona y no utiliza combinaciones:

DECLARE @ObjectName NVARCHAR(100)
SELECT @ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[tableSchema].[tableName]') AND [name] = 'columnName';
EXEC('ALTER TABLE [tableSchema].[tableName] DROP CONSTRAINT ' + @ObjectName)

Solo asegúrese de que columnName no tenga corchetes, ya que la consulta busca una coincidencia exacta y no devolverá nada si es [columnName].

BuceoSteve
fuente
1
Y esta respuesta funciona con esquemas distintos al predeterminado [dbo], a diferencia de cualquiera de las otras respuestas.
Contango
No lo he probado, pero puede intentar agregar un WHILE (@ObjectName NO ES NULO) alrededor, poner TOP 1 antes de SELECT (at) ObjectName = OBJECT_Name ([predeterminado ... y solo ejecutar EXEC ('ALTER TA ... if (at) ObjectName NO ES NULO.
ScubaSteve
66
Para hacer que este script sea idempotente, agregue IF @ObjectName IS NOT NULLantes del comando EXEC
Siete
3
No funciona para mí usando restricciones CHECK . [default_object_id])es 0 . Obtengo un valor NULL .
Kiquenet
Dulce y simple, pero de acuerdo con los documentos de Microsoft, esta forma de hacer las cosas no existirá para siempre. Hay una advertencia que indica que desaparecerá en la próxima versión docs.microsoft.com/en-us/sql/t-sql/statements/…
Hopeless
11

Para soltar la restricción de varias columnas:

declare @table_name nvarchar(256)

declare @Command nvarchar(max) = ''

set @table_name = N'ATableName'

select @Command = @Command + 'ALTER TABLE ' + @table_name + ' drop constraint ' + d.name + CHAR(10)+ CHAR(13)
from sys.tables t
join sys.default_constraints d on d.parent_object_id = t.object_id
join sys.columns c on c.object_id = t.object_id
     and c.column_id = d.parent_column_id
where t.name = @table_name and c.name in ('column1','column2','column3')

--print @Command

execute (@Command)
Ken Yao
fuente
5

Solución ampliada (tiene en cuenta el esquema de la tabla):

-- Drop default contstraint for SchemaName.TableName.ColumnName
DECLARE @schema_name NVARCHAR(256)
DECLARE @table_name NVARCHAR(256)
DECLARE @col_name NVARCHAR(256)
DECLARE @Command  NVARCHAR(1000)

set @schema_name = N'SchemaName'
set @table_name = N'TableName'
set @col_name = N'ColumnName'

SELECT @Command = 'ALTER TABLE [' + @schema_name + '].[' + @table_name + '] DROP CONSTRAINT ' + d.name
 FROM sys.tables t   
  JOIN sys.default_constraints d       
   ON d.parent_object_id = t.object_id  
  JOIN sys.schemas s
        ON s.schema_id = t.schema_id
  JOIN    sys.columns c      
   ON c.object_id = t.object_id      
    AND c.column_id = d.parent_column_id
 WHERE t.name = @table_name
    AND s.name = @schema_name 
  AND c.name = @col_name

EXECUTE (@Command)
Jorge García
fuente
3

Descarte todas las restricciones predeterminadas en una base de datos: seguro para el umbral nvarchar (max).

/* WARNING: THE SAMPLE BELOW; DROPS ALL THE DEFAULT CONSTRAINTS IN A DATABASE */ 
/* MAY 03, 2013 - BY WISEROOT  */
declare @table_name nvarchar(128)
declare @column_name nvarchar(128)
declare @df_name nvarchar(128)
declare @cmd nvarchar(128) 

declare table_names cursor for 
 SELECT t.name TableName, c.name ColumnName
 FROM sys.columns c INNER JOIN
     sys.tables t ON c.object_id = t.object_id INNER JOIN
     sys.schemas s ON t.schema_id = s.schema_id
     ORDER BY T.name, c.name

     open table_names
fetch next from table_names into @table_name , @column_name
while @@fetch_status = 0
BEGIN

if exists (SELECT top(1) d.name from sys.tables t join sys.default_constraints d on d.parent_object_id = t.object_id join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id where t.name = @table_name and c.name = @column_name)
BEGIN
    SET @df_name = (SELECT top(1) d.name from sys.tables t join sys.default_constraints d on d.parent_object_id = t.object_id join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id where t.name = @table_name and c.name = @column_name)
    select @cmd = 'ALTER TABLE [' + @table_name +  '] DROP CONSTRAINT [' +  @df_name + ']'
    print @cmd
    EXEC sp_executeSQL @cmd;
END

  fetch next from table_names into @table_name , @column_name
END

close table_names 
deallocate table_names
user2346877
fuente
No es válido si algunas columnas que tenían múltiples restricciones predeterminadas o restricciones de verificación creadas, solo se ejecutan para las restricciones principales 1 en la consulta.
Kiquenet
2

Ejecute este comando para examinar todas las restricciones:

exec sp_helpconstraint 'mytable' --and look under constraint_name. 

Se verá algo como esto: DF__Mytable__Column__[ABC123]. Entonces puedes simplemente soltar la restricción.

Inhailed al horno
fuente
No funciona para mí:exec sp_helpconstraint 'Roles2016.UsersCRM'
Kiquenet
@Kiquenet debería ser solo el nombre de la tabla: exec sp_helpconstraint 'Roles2016'
Baked Inhalf
Solo muestra constantes de clave externa. valor no constante constaint
Morez
2

Espero que esto pueda ser útil para quienes tienen un problema similar. En la ObjectExplorerventana, seleccione su base de datos => Tablas, => su tabla => Restricciones. Si el cliente se define en el tiempo de creación de la columna, puede ver el nombre predeterminado de la restricción, incluido el nombre de la columna. luego use:

ALTER TABLE  yourTableName DROP CONSTRAINT DF__YourTa__NewCo__47127295;

(el nombre de la restricción es solo un ejemplo)

Elnaz
fuente
2

La siguiente solución eliminará la restricción predeterminada específica de una columna de la tabla

Declare @Const NVARCHAR(256)

SET @Const = (
              SELECT TOP 1 'ALTER TABLE' + YOUR TABLE NAME +' DROP CONSTRAINT '+name
              FROM Sys.default_constraints A
              JOIN sysconstraints B on A.parent_object_id = B.id
              WHERE id = OBJECT_ID('YOUR TABLE NAME')
              AND COL_NAME(id, colid)='COLUMN NAME'
              AND OBJECTPROPERTY(constid,'IsDefaultCnst')=1
            )
 EXEC (@Const)
Abdur Rahman
fuente
0

Tenía algunas columnas que tenían múltiples restricciones predeterminadas creadas, así que creo el siguiente procedimiento almacenado:

CREATE PROCEDURE [dbo].[RemoveDefaultConstraints] @table_name nvarchar(256), @column_name nvarchar(256)
AS
BEGIN

    DECLARE @ObjectName NVARCHAR(100)

    START: --Start of loop
    SELECT 
        @ObjectName = OBJECT_NAME([default_object_id]) 
    FROM 
        SYS.COLUMNS
    WHERE 
        [object_id] = OBJECT_ID(@table_name) 
        AND [name] = @column_name;

    -- Don't drop the constraint unless it exists
    IF @ObjectName IS NOT NULL
    BEGIN
        EXEC ('ALTER TABLE '+@table_name+' DROP CONSTRAINT ' + @ObjectName)
        GOTO START; --Used to loop in case of multiple default constraints
    END
END
GO

-- How to run the stored proc.  This removes the default constraint(s) for the enabled column on the User table.
EXEC [dbo].[RemoveDefaultConstraints] N'[dbo].[User]', N'enabled'
GO

-- If you hate the proc, just get rid of it
DROP PROCEDURE [dbo].[RemoveDefaultConstraints]
GO
Anztenney
fuente
0

Útil para algunas columnas que tenían múltiples default constraints or check constraints creadas:

Guión https://stackoverflow.com/a/16359095/206730 modificado

Nota: este script es para sys.check_constraints

declare @table_name nvarchar(128)
declare @column_name nvarchar(128)
declare @constraint_name nvarchar(128)
declare @constraint_definition nvarchar(512)

declare @df_name nvarchar(128)
declare @cmd nvarchar(128) 

PRINT 'DROP CONSTRAINT [Roles2016.UsersCRM].Estado'

declare constraints cursor for 
 select t.name TableName, c.name ColumnName, d.name ConstraintName, d.definition ConstraintDefinition
 from sys.tables t   
 join sys.check_constraints d  on d.parent_object_id = t.object_id  
 join sys.columns c  on c.object_id = t.object_id      
 and c.column_id = d.parent_column_id
 where t.name = N'Roles2016.UsersCRM' and c.name = N'Estado'

open constraints
fetch next from constraints into @table_name , @column_name, @constraint_name, @constraint_definition
while @@fetch_status = 0
BEGIN
    print 'CONSTRAINT: ' + @constraint_name
    select @cmd = 'ALTER TABLE [' + @table_name +  '] DROP CONSTRAINT [' +  @constraint_name + ']'
    print @cmd
    EXEC sp_executeSQL @cmd;

  fetch next from constraints into @table_name , @column_name, @constraint_name, @constraint_definition
END

close constraints 
deallocate constraints
Kiquenet
fuente
0

Siempre genere scripts y revise antes de ejecutar. Debajo del guión

  select 'Alter table dbo.' + t.name + ' drop constraint '+ d.name  
  from sys.tables t
  join sys.default_constraints d on d.parent_object_id = t.object_id
  join sys.columns c on c.object_id = t.object_id
       and c.column_id = d.parent_column_id
  where c.name in ('VersionEffectiveDate','VersionEndDate','VersionReasonDesc')
  order by t.name
usuario6232480
fuente
0
declare @table_name nvarchar(100)
declare @col_name nvarchar(100)
declare @constraint nvarchar(100)
set @table_name = N'TableName'
set @col_name = N'ColumnName'

IF EXISTS (select       c.*
    from        sys.columns c 
    inner join  sys.tables t on t.object_id = c.object_id
    where       t.name = @table_name
    and         c.name = @col_name) 
BEGIN

select @constraint=d.name
from 
sys.tables t
join sys.default_constraints d on d.parent_object_id = t.object_id
join sys.columns c on c.object_id = t.object_id
and c.column_id = d.parent_column_id
where 
t.name = @table_name
and c.name = @col_name

    IF LEN(ISNULL(@constraint, '')) <> 0
    BEGIN
        DECLARE @sqlcmd VARCHAR(MAX)
        SET @sqlcmd = 'ALTER TABLE ' + QUOTENAME(@table_name) + ' DROP CONSTRAINT' + 
        QUOTENAME(@constraint);
        EXEC (@sqlcmd);

    END

END
GO
usuario2832577
fuente
0
declare @ery nvarchar(max)
declare @tab nvarchar(max) = 'myTable'
declare @qu nvarchar(max) = 'alter table '+@tab+' drop constraint '

select @ery = (select bj.name from sys.tables as tb 
inner join sys.objects as bj 
on tb.object_id = bj.parent_object_id
where tb.name = @tab and bj.type = 'PK')

exec(@qu+@ery)

Echar un vistazo.

usuario8310624
fuente
2
Incluso si su código trae una solución, es mejor que lo envuelva con un poco de explicaciones de por qué resuelve la pregunta.
Fabien